如果你還沒有看過前傳,可以參看前情回顧:
回顧1. 題目是模擬實現es5中原生bind函式;
回顧2. 我們通過4種遞進實現達到了完美狀態;
回顧3. 可是es5-shim中的實現,又讓我們大跌眼鏡...
es5-shim實現方式原始碼貼在了最後,我們看看他做了什麼奇怪的事情:
1)從結果上看,返回了bound函式。
2)bound函式是這樣子宣告的:
bound = function
(binder)
;
答案肯定是沒抽風,他這樣做是有理由的。
你可能不知道,每個函式都有length屬性。對,就像陣列和字串那樣。函式的length屬性,用於表示函式的形參個數。更重要的是函式的length屬性值是不可重寫的。我寫了個測試**來證明:
function
test
(){}
test.length
// 輸出0
test.hasownproperty
('length')
// 輸出true
object.getownpropertydescriptor
('test', 'length')
// 輸出:
// configurable: false,
// enumerable: false,
// value: 4,
// writable: false
說到這裡,那就好解釋了。
es5-shim是為了最大限度的進行相容,包括對返回函式length屬性的還原。如果按照我們之前實現的那種方式,length值始終為零。
所以:既然不能修改length的屬性值,那麼在初始化時賦值總可以吧!
於是我們可通過eval和new function的方式動態定義函式來。
同時,很有意思的是,原始碼裡有這樣的注釋:
// *** build a dynamic function
with desired amount of arguments is the only
// way to set the length property
of a function.
// in environments where content security policies enabled (chrome extensions,
// for ex.) all
useof eval or
function costructor throws an exception.
// however in
allof these environments function.prototype.bind exists
// and so this code will never be executed.
他解釋了為什麼要使用動態函式,就如同我們上邊所講的那樣,是為了保證length屬性的合理值。但是在一些瀏覽器中出於安全考慮,使用eval或者function構造器都會被丟擲異常。但是,巧合也就是這些瀏覽器基本上都實現了bind函式,這些異常又不會被觸發。
so, what a coincidence!
我們明白了這些,再看他的進一步實現:
if (!iscallable(target))
這是為了保證呼叫的正確性,他使用了iscallable做判斷,iscallable很好實現:
iscallable = function
iscallable
(value)
}
重設繫結函式的length屬性:
var boundlength = max(0, target.length - args.length);
if (this
instanceof bound) else
if (target.prototype)
當然,es5-shim裡還歸納了幾項todo...
// todo
// 18. set the [[extensible]] internal property of f to true.
// 19. let thrower be the [[throwtypeerror]]
function
object
(13.2.3)
.// 20. call the [[defineownproperty]] internal method of f with
// arguments "caller", propertydescriptor , and
// false.
// 21. call the [[defineownproperty]] internal method of f with
// arguments "arguments", propertydescriptor ,
// and
false.
// 22. return f.
比較簡單,我就不再翻譯了。
bind: function
bind(that)
var args = array_slice.call(arguments, 1);
var bound;
var binder = function ()
return
this;
} else
};var boundlength = max(0, target.length - args.length);
var boundargs = ;
for (var i = 0; i < boundlength; i++)
if (target.prototype)
return bound;
}
通過學習es5-shim的原始碼實現bind方法,結合前一篇,希望讀者能對bind和js包括閉包,原型原型鏈,this等一系列知識點能有更深刻的理解。
同時在程式設計上,尤其是邏輯的嚴密性上,有所積累。
從一道php面試題說起
面試題目 setcookie name test echo cookies name 請說出程式結果 能說出第一次與第二次的區別者加分 本來一開始我認為不就是設定乙個cookie,然後讀出來的問題,但是被那個後面的提示搞迷惑了從來沒有想過這樣的問題。面試的時候也沒有想出答案,後來在面試官的指點下搞清...
從一道面試題開始說fork
自 http blog.csdn.net yuwenliang archive 2010 01 18 5209239.aspx 給出如下c程式,在linux下使用gcc編譯 1 include stdio.h 2 include sys types.h 3 include unistd.h 4 5 ...
從一道「微信面試題」能學到什麼?
為什麼取得是這樣的乙個題目,這個其實不難理解,作為bat中的一員,tx的面試題往往會成為一段時間之內的某些領域的風向標。這些面試題可能並不難,但是涵蓋了很多方面的知識,需要我們謹慎應對。lazyman mulige hi this is mulige lazyman mulige sleep 10 ...