從一道面試題,到「我可能看了假原始碼 2

2021-07-27 11:36:30 字數 3222 閱讀 8447

如果你還沒有看過前傳,可以參看前情回顧:

回顧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 ...