筆記 探索js 的this 物件 第二部分

2022-07-09 12:48:12 字數 3897 閱讀 9142

了解this 物件之後 我們明白了this 物件就是指向呼叫函式的作用域

那麼接下來我們便要清除函式究竟在哪個作用域呼叫

找到呼叫的作用域首先要了解一下幾點:

1、呼叫棧: 呼叫棧就是一系列的函式,表明當前函式是由哪些上層函式呼叫的包括它自身,我們關心的呼叫位置就在當前正在執行的函式的前乙個呼叫中。

function

baz()

function

bar()

function

foo()

baz()

//baz的呼叫位置是 全域性作用域

這段**的意思是,函式再哪個區域被呼叫 那個區域就是它的執行環境

找到了呼叫位置就要理解一下函式對 this物件的繫結了

一般分為一下4種:

1、預設繫結

指函式在呼叫的過程中沒有任何干涉呼叫位置的** 瀏覽器引擎根據呼叫棧預設繫結

預設繫結,函式的this 物件會指向了window 物件 而在嚴格模式下函式訪問this 會顯示undefined

例子:

function

foo()

var a = "i'm window";

foo();

//輸出2 因為全域性變數也是window物件的屬性

2、隱式繫結

函式沒有呼叫任何方法繫結 而是在呼叫時根據物件上下文繫結了this 的作用域

看一下下面的例子

function

foo()

var obj =

obj.foo();

//通過obj 呼叫 函式foo,所以foo的this 物件繫結在了 obj上

//嚴格來說 函式foo 不屬於obj物件 但由於函式是通過obj 引用並呼叫的所以this 指向了obj

另外物件呼叫鏈中只有最靠近被呼叫函式那層會影響函式的呼叫位置

即:函式在某乙個物件裡面 通過那個物件呼叫函式 this永遠指向那個物件

例如:

function

bar()

var obj2 =

var obj1 =

obj1.obj2.bar();

這裡的意思是:obj1 呼叫 obj2 然後obj2 再呼叫 bar這個函式引用

從邏輯上說 bar這個函式呼叫怎麼也是屬於 obj2 吧

另外dom 的事件繫結**函式也會把this 繫結在執行事件的 dom元素物件上

小分支:

2.1、隱式丟失

隱式繫結的函式會丟失原來的this所引用的物件

丟失後的this 會引用到全域性物件或 undefined

例1:把函式的引用賦值給全域性變數 會丟失原來的this 繫結

function

foo()

var obj =

var bar =obj.foo;

//把obj foo屬性裡面對 foo 函式的引用賦值給了全域性變數bar

var a = "global window";

bar();

這裡的函式 foo 的引用雖然是obj 裡面的乙個屬性值,但是後面卻把函式的引用賦值給了乙個全域性變數並且在全域性環境執行,所以foo 的this 物件指向了window 物件

其實這裡真正的誤區是我們一直以為在物件字面量中屬性值為函式就是函式this 繫結的區域,其實不然

回顧一下第一部分的話,函式在**呼叫,那裡才是它this 物件繫結的環境

所以這次函式 foo的引用在(儲存在了bar中)在全域性呼叫所以this 指向了全域性

例2:把函式的引用當作引數傳進另外乙個函式被執行 會造成隱式丟失

function

foo()

function

dofoo(fn)

var obj =

var a = "global window";

dofoo(obj.foo);

這裡 dofoo 的輸出結果是  "global window"

同時,**函式也會造成隱式丟失

settimeout(obj.foo,1000);//

"global window"

3、顯式繫結

例如:

function

foo()

var obj =

//把foo函式繫結在obj 上執行

foo.call(obj);

//i'm obj

3.1、硬繫結

通過提供的方法,將函式繫結在某一物件上執行

例:

function

foo()

var obj =

settimeout(

function

timer(),1000);//

i'm obj

obj.call(window);

//硬性繫結之後 無法再繫結其他物件

除了這兩個 es5 語法還定義了新方法 bind()

例:

function

foo(num)

var obj =

var bar = foo.bind(obj);//

把foo 函式的引用繫結在了 obj上

var result = bar(3);

console.log(result);

//5

new 繫結:

js 的new 關鍵字不等同於其他物件導向語言裡的new

js 的new 關鍵字僅僅是呼叫它的目標函式而已

1、呼叫new 關鍵字會建立乙個新物件

2、新物件會與函式的原型連線

3、將函式的this 繫結到了新物件上

4、如果函式沒有返回指定的新物件 那麼就會返回乙個預設的物件

例:

function

foo()

var bar = new

foo();

console.log(bar.a);

上例中我們通過new 將foo函式例項化 並將this 指標指向了bar

於是bar 便擁有了函式中的 a屬性

以上四種繫結的優先順序

預設繫結最低

隱式繫結低於顯示繫結

隱式繫結又低於 new繫結

而new 與顯示繫結其實兩個本身的並沒有什麼影響很難說明優先順序

如下例:

function

foo(arg1)

var obj ={};

var bar =foo.bind(obj);

//將foo 函式的引用繫結在obj 上

//然後將obj 上對函式foo 的引用傳值給 bar

bar(2);

console.log(obj.a);

//現在將引用這 foo.bind(obj)的變數bar 例項化

var baz = new bar(5);

console.log(baz.a);//5

//此操作沒有修改obj 的屬性a 值,並且把新值新增到了新的物件上 baz

小結:這部分內容主要講述了函式的this繫結位置以及各種的繫結方式,有如下結論

1、當函式被new 例項化時,this 物件指向新返回的物件

3、函式在某個物件字面量裡面呼叫,this繫結在了這個物件字面量裡面

4、以上都沒有被操作,在非嚴格模式下函式的this 指向了window物件,嚴格模式下為undefined

深度探索C 物件模型筆記 第二章

explicit關鍵字能夠制止單參建構函式被當作型別轉換運算子.編譯器的隱式操作只是為了滿足編譯器本身的需求,而不是程式本身,乙個被編譯器隱式生成的預設建構函式,多數情況下對於程式本身來說是無用的.如果乙個類沒有任何建構函式,但類中的乙個非內建型別成員變數有預設建構函式,那麼這個類被隱式生成的預設建...

深度探索C 物件模型 第二章讀書筆記

1.如果設計者提供多個constructors,但其中都沒有default constructor呢?編譯器會擴張現在的每一次constructors,將 用以呼叫所有必要之default constructor 的程式 加進去。它不會合成乙個新的default constructor,因為其他由u...

js筆記第二週2

迴圈 數值判斷函式 isnan 自定義函式 匿名函式 函式的立即呼叫 按鈕事件 byid方法 for迴圈 while迴圈 do while迴圈 for 初始化引數 迴圈條件 增量或者減量 while 迴圈條件 dowhile 條件 其中do while是先執行一次然後再判斷。for in迴圈 遍歷陣...