在前幾篇博文中,關於this理解問題,我都有提到。 自認為理解很到位了,結果專案中,經常被this搞蒙頭。簡單的可能還好,如果函式呼叫位置不太明確的,只能大概加估計了。再次複習,加深理解。
js的作用域是基於函式的作用域的,在談到this指向問題時,很多情況下都是結合函式來說的。this到底是什麼,是個什麼東西。單獨的this就是js的乙個關鍵字,無任何函式,函式呼叫時,他便指向乙個物件。在理解問題之前,我們先得理解呼叫位置,函式呼叫棧。然後在介紹結合四法則,結合理解this
呼叫棧一種資料結構,可以理解為函式執行時呼叫的所有函式
呼叫位置函式在**中被呼叫的地方,包含函式呼叫的東西,或者說上下文。為什麼需要介紹這個,this就是在函式呼叫時繫結的,需要找到呼叫位置,才能方便分析出this的指向。先來看看這段**
function baz ()
function bar ()
function foo ()
baz() ----> baz呼叫位置
我這裡依照之前的debug結果,注發布結果,就不再細分析。直觀的,我們不便分析出呼叫位置,我們可以結合瀏覽器或者編輯器debug工具,除錯檢視函式呼叫棧。
我們知道this是在函式呼叫時繫結的(前面已經提過),上面已經理解了呼叫位置。那麼在函式呼叫時,this是如何繫結的。這裡需要重點結合4個法則分析。
函式呼叫不帶任何修飾時,預設繫結到window頂層物件這個很簡單,就是普通函式呼叫,this一般都是繫結到global.
實列**
function foo ()
var a = "oop ,blobal!!!";
var obj =
//帶修飾的foo呼叫, 帶物件引用的,函式呼叫
obj.foo() ===> obj
//不帶修飾的呼叫
foo() ----> global
函式呼叫處,是否包含上下文物件。如果函式位置出,擁有上下文物件。那麼this則指向它。這裡我叫他帶修飾的函式呼叫。如果函式呼叫位置處帶修飾,比如含有物件的引用。此時函式中的this則指向這個物件.上面實列有說明,結合字面意思的實列很容易理解。重點說說隱式繫結丟失。這個是我這次複習this的主要原因。這個概念主要包括兩個小內容。
賦值時丟失
隱式賦值丟失
解釋:第一中很常見,就是將物件的方法賦值到物件外面的變數。導致this繫結的物件丟失。應用預設繫結
.......
var a = obj.foo
a() // this---> window
第二種發生在函式當作引數傳遞的時候, 函式當作引數傳遞,其實也是乙個隱式賦值
比如下面這樣,傳入值得時候,方法內部this得繫結就會丟失去,使用預設繫結 。當然這取決函式是否執行在嚴格模式下。只有在非嚴格模式下,才會使用預設邦定。
//定時器傳入隱式繫結函式
settimout(obj.foo) //這裡的foo是obj物件的乙個方法,此處省略具體宣告
實列
var obj =
foo.call(obj)
這種方法,用來解決隱式繫結丟失問題。但是目前還沒發,需要稍作修改。即使顯示繫結變種,
實列
var obj =
// 隱式繫結丟失
var dofoo = obj.foo //this---> window
//硬繫結
var dofoo = function ()
dofoo() ----> this--obj
硬繫結: 總的來說是解決了隱式繫結丟失問題,但同時也帶來了問題,this固定,不能在修改。
硬繫結使用改進 , bind. 負責接受值,返回
function foo (something)
function bind (fn, obj)
}var obj = {}
var dofoo = bind(foo, obj)
var a= dofoo(3)
es5內建bind
上面的使用方式可以修改一下
var dofoo = foo.bind(obj) 這裡只需要傳入需要繫結this的物件即可。
通常在js opp的時候,會用到。經常會聽到程式設計師調侃,沒得物件new乙個就完事兒了。說的就是著玩兒。 在js中通過new關鍵字 構造函式呼叫,會生成新物件, 這期間構造內的this會指向 新物件new 構造函式呼叫發生的事情:
1.建立新物件
2.新物件會鏈結__proto__
3.新物件會繫結到函式呼叫的this
4.如果函式呼叫沒有返回物件,那麼new 表示式呼叫會自動返回新物件。
在前面說的四法則中,在實際的場景中優先順序。
這裡重點說說 硬繫結和 new 構造呼叫優先順序順序
硬繫結通過包裝函式,包裝內層的顯示繫結函式呼叫, 繫結this。這裡使用es5的內建bind。他會返回乙個含有顯示繫結的硬繫結函式。這個外層函式會忽略this的繫結。
new構造他會修改硬繫結的this指向。以此看來 new優先順序高於硬繫結
實列
var obj = {}
function foo(something)
var dofoo = foo.bind(obj)
dofoo (3) //通過硬繫結對obj設定屬性
obj.a = 3
//通過new 改變內層this指向
var bar = new dofoo(2)
//可以看到 obj.a == 3 依舊未變
但是bar.a = 2 說明了new 改變了內部this指向
應用: 分布應用或者柯里化, new 結合bind使用。
function foo (a, b)
或者var dofoo = foo.bind(null, 2);
dofoo(3)
使用null作為忽略this。避免不必要this的繫結. 雖然方便,但也存在問題,他會應用預設繫結。導致一系列問題.
安全this
未必免上述情況, 這裡介紹一種。更安全忽略this方法
//建立乙個空物件,用於this的繫結
var empty = object.create(null) //這樣建立的物件不存在原型關聯
//同樣是上述面列子,我們可以這樣呼叫foo
或者var dofoo = foo.bind(empty, 2)
dofoo(3)
這樣應用預設規則 Mac IDEA快捷鍵精華版
1.command n 快速建立方法,例如getter,setter,override等 2.option command t 包圍 使用if.else,try.catch,for,synchronized等包圍選中的 3.自動結束 行末自動新增分號 4.j,mid.button click 快速檢...
自動化測試基礎(精華版)
最近事情比較忙,好久沒更新部落格了。今天抽空來一篇自動化基礎的。首先來看一下什麼是自動化測試,我們前面說過什麼是軟體測試,來回顧一下概念,軟體測試 通過手工或自動化手段來檢測軟體中的錯誤和缺陷的過程。那麼自動化測試呢?就是通過自動化手段來檢測軟體中的錯誤和缺陷的過程了,ok,這樣說面試時是ok的,有...
Oracle 時間 問題總結精華版
1.oracle中如何獲取系統當前時間 oracle中如何獲取系統當前時間 select to char sysdate,yyyy mm dd hh24 mi ss from dual oracle裡獲取乙個時間的年 季 月 周 日的函式 select to char sysdate,yyyy fr...