上篇《2.2this
全面解析》了解到函式呼叫中this
繫結的四條規則,找到函式的呼叫位置並判斷應當應用哪條規則。這篇學習假設某個呼叫位置可以應用多條規則,就必須給這些規則設定優先順序。
毫無疑問,預設繫結的優先順序是四條規則中最低的,所以可以先不考慮它。
function foo()
var obj1 =
var obj2 =
obj1.foo() // 2
obj2.foo() // 3
obj1.foo.call(obj2) // 3
obj2.foo.call(obj1) // 2
結果:顯式繫結優先順序更高,也就是說在判斷時應當先考慮是否可以應用顯式繫結。
function foo(something)
var obj1 =
var obj2 = {}
obj1.foo(2)
console.log(obj1.a) // 2
obj1.foo.call(obj2, 3)
console.log(obj2.a) // 3
var bar = new obj1.foo(4)
console.log(obj1.a) //2
console.log(bar.a) //4
結論:new
繫結比隱式繫結優先順序高
function foo(something)
var obj1 = {}
var bar = foo.bind( obj1 )
bar(2)
console.log(obj1.a) //2
var baz = new bar(3)
console.log(obj1.a) //4
console.log(baz.a) //4
解析:
bar
被硬繫結到obj1
上,但是new bar(3)
並沒有把obj1.a
修改為3
new
修改了硬繫結(到obj1
的)呼叫bar(...)
中的this
因為使用了new
繫結,得到了乙個名字為baz
的新物件,並且baz.a
的值是3
再回頭看看之前介紹的 「裸」 輔助函式bind
:
function bind(fn, obj)
}
因為看起來在輔助函式中new
操作符的呼叫無法修改this
繫結,但是在剛才的**中new
確實修改了this
繫結。
實際上, es5 中內建的function.prototype.bind(...)
更加複雜。
下面是引用 mdn 提供的一種bind(...)
實現:
if (!function.prototype.bind)
var aargs = array.prototype.slice.call(arguments, 1),
ftobind = this,
fnop = function () ,
fbound = function ()
fnop.prototype = this.prototype
fbound.prototype = new fnop()
return fbound
}}
拓展:
這種bind(..)
是一種polyfill
** (polyfill
就是我們常說的刮牆用的膩子,polyfill
**主要用於舊瀏覽器的相容,比如說在舊的瀏覽器中並沒有內建bind
函式,因此可以使用polyfill
**在舊瀏覽器中實現新的功能),對於new
使用的硬繫結函式來說,這段polyfill
**和 es5 內建的bind(..)
函式並不完全相同。由於polyfill
並不是內建函式,所以無法建立乙個不包含.prototype
的函式。因此會具有一些***。如果你要在new
中使用硬繫結函式並且依賴polyfill
**的話,一定要非常小心。
this instanceof fnop && othis ? this : othis
// ... 以及
fnop.prototype = this.prototype
fbound.prototype = new fnop()
簡單來說,這段**會判斷硬繫結函式是否被new
呼叫,如果是的話就會使用新建立的this
替換硬繫結的this
。
那為什麼要在new
中使用硬繫結函式呢? 直接使用普通函式不是更簡單嗎?之所以要在
new
中使用硬繫結函式,主要目的是預先設定函式的一些引數,這樣在使用new
進行初始化時就可以只傳入其餘的引數。bind(...)
的功能之一就是可以把除了第乙個引數(第乙個引數用於繫結this
)之外的其他引數都傳給下層的引數(這種技術稱為「部分應用」,是「柯里化」的一種)。
function foo(p1, p2)
// 之所以使用 null 是因為在本例中並不關心硬繫結的 this 是什麼
// 反正使用 new 時 this 會被修改
var bar = foo.bind(null, "p1")
var baz = new bar("p2")
console.log(baz.val)
---------------------------------------------
> p1p2
可以按照下面的順序來根據優先順序來判斷函式在某個呼叫位置應用的是哪條規則:
函式是否在new
中呼叫(new
繫結)?如果是的話this
繫結的是新建立的物件(var bar = new foo()
)
函式是否在某個上下文物件中呼叫(隱式繫結)?如果是的話,this
繫結的是哪個上下文物件(var bar = foo()
)
如果都不是的話,使用預設繫結。如果再嚴格模式下,就繫結到undefined
, 否則繫結到全域性物件(var bar = foo()
)
this學習(三)this繫結規則的優先順序
目錄 一 顯式繫結 vs 隱式繫結 二 new繫結 vs 隱式繫結 三 顯示繫結 vs new繫結 四 總結 在前面的學習中,有預設繫結 顯式繫結 隱式繫結 new繫結,這4種規則當中,預設繫結的優先順序一定是最低的,那麼其它三個規則的優先順序到底是怎麼樣的呢?例子 function foo var...
CSS 優先順序規則
優先順序是瀏覽器是通過判斷哪些屬性值與元素最相關以決定並應用到該元素上的。優先順序僅由選擇器組成的匹配規則決定的。優先順序就是分配給指定的css宣告的乙個權重,它由匹配的選擇器中的每一種選擇器型別的數值決定。下列是乙份優先順序逐級增加的選擇器列表 當 important規則被應用在乙個樣式宣告中時,...
C語言 優先順序規則
理解c語言宣告的優先順序規則 宣告從它的名字開始,然後按照優先順序順序依次讀取 優先順序從高到低依次是 2.1 宣告中被括號起來的那部分 2.2 字尾操作符 括號 表示是乙個函式 表示是乙個陣列 2.3 字首操作符 星號 表示 指向 的指標 如果const和 或 volatile關鍵字的後面緊跟型別...