Javascript 手動造輪子

前言

上次發了一下手動實現Promise https://segmentfault.com/a/11... 以後有猿友問我私聊我其它的像bind, call這些有沒有標準的寫法。個人回答是沒有,像這些api咱們只能仿照它的功能,只能作得很像很像,可是絕對標準的答案是沒有的,就像我以前的那篇文章,也只是在參照PromiseA+規範去仿寫。好多Promise特有的API和特性也沒有寫進去,由於個人目的是經過手寫來讓你們學習promise,如今的自動化構建工具及其插件這麼多,功能這麼強大咱們沒有那麼多的要求去爲了實現兼容性而本身手動實現一遍。前端

包括我本身也是,面試的時候確實會問一些能不能手動實現一個什麼什麼的,可是這個目的並非招你過來手寫API的,由於我認爲手動造輪子或造框架要求你的js基本功必須紮實,想去實現一個東西,必需要完徹底全地瞭解它才能夠。手動實現代碼的過程當中每每也能看出一我的的編程思想。 固然,能寫出來或者模擬地很像那確定是很是好的。react

這篇文章我建議你們不要刻意去收藏,去記從而去應付面試, 這樣的學習方法不推薦(固然之前我也這樣),這種文章讀幾遍就好了,最主要地是以後去看這些API的用法以及特色,以及發掘每一個人的編程思想, 而後本身寫下來,甚至寫的更好,記憶更加深入。而且我也建議你們項目中遇到問題以後,第一時間不要去想着 複製錯誤信息而後 百度一下,必應一下,google一下,這樣意義不大,正確的作法我以爲是先經過錯誤信息先本身找到錯誤根源,想想爲何會出錯,爲何達不到你想要的結果,而後總結經驗, 若是是一些框架API或者插件,遇到問題最好先去文檔裏面認真的看一下,而後學着本身手動解決。以前的我學新東西新技術很愛看視頻,百度搜。可是如今的話我更願意去看它的文檔,有時間去逛它的社區,固然了, 新東西出來不要去盲目地學 學技術要本着一精多專的目的去學, 不過不管是什麼方向, js的基礎是很是很是重要的。面試

好了,廢話太多了,進入正題。。。算法

手動實現Call

這些API的特色以及具體用法我就不介紹了,相信你若是奔着手動實現的方向來看,那麼你必定對它很瞭解編程

核心: this永遠指向最後調用它的對象segmentfault

代碼:api

Function.prototype.myCall = function(context, ...args) {
    context['key'] = this;
    context.key(...args);
    delete context.key;
}

寫到這裏,call基本的特色已經實現,其實面試中通常寫到這裏也就經過了,可是實際上卻還差很遠。以前個人那篇文章也是如此,只是實現了基本的功能。由於完徹底全的實現確實會花費不少時間.
仍是簡單說一下吧,咱們知道call中是能夠傳入一些基本類型的,而且咱們如今的這種實現方式增長了一個顯示的key屬性,實際上你在調用真正的call的時候去打印this是沒法發現這些額外屬性的,那麼咱們就仿照這些特性再去優化,接近一下promise

Function.prototype.myCall = function(context, ...args) {
    let newContext = context;
    if ([null, undefined].includes(context) ) {
        newContext = window || {};
    }
    switch (typeof context) {
        case 'number': {
            newContext = new Number(context);
            break;
        }
        case 'boolean': {
            newContext = new Boolean(context);
            break;
        }
        case 'string': {
            newContext = new String(context);
            break;
        }
    }

    Object.defineProperty(newContext, 'key', {
        value: this,
        configurable: true,
        enumerable: false,
    });
    newContext.key(...args);
    delete newContext.key;
}

這裏就差很少了,後面的我就直接上代碼了架構

實現apply

Function.prototype.myApply = function(context, obj) {
    if (typeof obj !== 'object') {
        throw new TypeError('CreateListFromArrayLike called on non-object')
    }
    let newContext = context;
    if ([null, undefined].includes(context)) {
        newContext = window;
    }
    switch (typeof context) {
        case 'number': {
            newContext = new Number(context);
            break;
        }
        case 'boolean': {
            newContext = new Boolean(context);
            break;
        }
        case 'string': {
            newContext = new String(context);
            break;
        }
    }
    Object.defineProperty(newContext, 'key', {
        value: this,
        configurable: true,
        enumerable: false,
    });
    newContext.key(...obj);
    delete newContext.key;
};

實現bind

Function.prototype.myBind = function(context, ...args) {
    let _this = this;
    let newFun = (...args2) => {
        _this.call(context, ...args, ...args2)
    };
    newFun.prototype = Object.create(_this.prototype)
    return newFun
};

實現Promise

https://segmentfault.com/a/11...app

實現Object.create

Object.create = Object.create || function(obj){

    var F = function(){};

    F.prototype = obj;

    return new F();

}

實現new

function myNew(fun) {
    if (typeof fun !== 'function') throw new TypeError('fun is not a constructor')
    return function() {
        let obj = { '__proto__': fun.prototype }
        fun.call(obj, ...arguments)
        return obj
    }
}

實現reduce

Array.prototype.myReduce = function(fn, orginal = '__orginal') {
    let copy = [...this]
    if (orginal !== '__orginal') {
        copy.unshift(orginal)
    }
    while (copy.length > 1) {
        let prev = copy.shift()
        let next = copy.shift()
        copy.unshift(fn(prev, next))
    }
    return copy[0]
}

總結

仍是以前那句話,這些東西不推薦去硬記(若是你爲了應付面試當我沒說),目的是掌握它而後可以本身寫下來。最後再說一下,雖然咱們如今都是站在巨人的肩旁上,不少東西咱們拿來即用就能夠,可是是否還要有這種需求呢?有,固然有,任何東西都不是絕對完美的,react好用,可是你知道setState到底應該同步仍是異步的口水大戰嗎? 完美是由於適應,你能手寫是由於我知道你絕對理解,好多公司有本身的框架,也都是會借鑑,仿寫甚至在源碼的基礎上去優化成爲適應自身公司業務的框架。你想一想,對API的核心原理以及用法都不理解,不知道JS線程與GUI渲染線程互斥,不理解模塊化的意義, 不知道設計原則,不清楚何爲設計何爲模式,你又怎麼進階到手寫源碼,架構底層或是對前端性能進行優化呢? 因此,不要着急去背,哪裏不會哪裏沒有理解就認真地去理解它。接下來我應該會發一系列的算法文章,若是有興趣的能夠提早關注一下, 固然了,若是你以爲對你有幫助, 麻煩點個贊,若是以爲哪裏寫的不嚴謹麻煩指出,共勉!

相關文章
相關標籤/搜索