成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

javascript:this 關(guān)鍵字

shixinzhang / 2783人閱讀

摘要:執(zhí)行完以后,將該匿名函數(shù)賦值給。上述代碼其實(shí)等價(jià)于執(zhí)行如下的代碼,函數(shù)回調(diào)場(chǎng)景基本原理可以看到,把一個(gè)定義有關(guān)鍵字的函數(shù)作為其它函數(shù)的回調(diào)函數(shù),是危險(xiǎn)的,因?yàn)樵谶\(yùn)行期會(huì)被重新賦值,上述例子很直觀的描述了這一點(diǎn),之所以報(bào)錯(cuò),是因?yàn)橹赶蛄恕?/p>

前言

看過(guò)[阮一峰]()的關(guān)于 this 的教程,講了很多比較好的例子,但沒(méi)有對(duì)其本質(zhì)的東西解釋清楚,而且部分例證存在問(wèn)題;于是,打算重寫(xiě)本章節(jié),從this的本質(zhì)入手;

本文為作者的原創(chuàng)作品,轉(zhuǎn)載需注明出處;

this 是什么?

this可以理解為一個(gè)指針,指向調(diào)用對(duì)象;

判斷 this 是什么的四個(gè)法則

官網(wǎng)定義

先來(lái)看第一段官方的解釋,

In JavaScript, as in most object-oriented programming languages, this is a special keyword that is used within methods to refer to the object on which a method is being invoked. The value of this is determined using a simple series of steps:

If the function is invoked using Function.call or Function.apply, this will be set to the first argument passed to call/apply. If the first argument passed to call/apply is null or undefined, this will refer to the global object (which is the window object in Web browsers).

If the function being invoked was created using Function.bind, this will be the first argument that was passed to bind at the time the function was created.

If the function is being invoked as a method of an object, this will refer to that object.

Otherwise, the function is being invoked as a standalone function not attached to any object, and this will refer to the global object.

大致翻譯如下,
this是這么一個(gè)特殊的關(guān)鍵字,它是用來(lái)指向一個(gè)當(dāng)前正在被調(diào)用( a being invoked )方法的調(diào)用對(duì)象的;( 等等,這句話其實(shí)隱藏了一個(gè)非常關(guān)鍵的信息,那就是this是在運(yùn)行期 生效的,怎么生效的?在運(yùn)行期,this被賦值,將某個(gè)對(duì)象賦值給this,與聲明期無(wú)關(guān),也就是說(shuō),this是運(yùn)行期相關(guān)的 );this的賦值場(chǎng)景,歸納起來(lái),分為如下四種情況,

如果方法是被Function.call或者Function.apply調(diào)用執(zhí)行.... bla..bla..
參考 function prototype call 小節(jié)

如果是被Function.bind... bla...bla
參考 function prototype bind 小節(jié)

如果某個(gè)方法在運(yùn)行期是被一個(gè)對(duì)象( an object )調(diào)用( 備注:這里為了便于理解,我針對(duì)這種情況,自己給起了個(gè)名稱叫關(guān)聯(lián)調(diào)用 ),在運(yùn)行期,會(huì)將該 object 的引用賦值給該方法的this。
備注:被一個(gè)對(duì)象調(diào)用?何解?其實(shí)就是指語(yǔ)句obj.func(),這個(gè)時(shí)候,func()方法內(nèi)部的this將會(huì)被賦值為obj對(duì)象的引用,也就是指向obj;

如果該方法在運(yùn)行期被當(dāng)做一個(gè)沒(méi)有依附在任何 object 上的一個(gè)獨(dú)立方法被調(diào)用(is being invoked as a standalone function not attached to any object ),那么該方法內(nèi)部的this將會(huì)被賦值為全局對(duì)象(在瀏覽器端就是 windows )
獨(dú)立方法 ( standalone function )?在運(yùn)行期,如果func方法被obj關(guān)聯(lián)調(diào)用的,既是通過(guò)obj.func()的方式,那么它就不是standalone的;如果是直接被調(diào)用,沒(méi)有任何對(duì)象關(guān)聯(lián),既是通過(guò)func()調(diào)用,那么這就是standalone的。

this 運(yùn)行期相關(guān)

官網(wǎng)定義 2

再來(lái)看另外一句非常精煉的描述,來(lái)加深理解

The this keyword is relative to the execution context, not the declaration context.

this關(guān)鍵字與運(yùn)行環(huán)境有關(guān)而與聲明環(huán)境無(wú)關(guān);(補(bǔ)充,而作用域鏈閉包是在函數(shù)的聲明期創(chuàng)建的,參考創(chuàng)建時(shí)機(jī))

補(bǔ)充,是如何與函數(shù)的運(yùn)行期相關(guān)的,參考this 指針運(yùn)行時(shí)賦值

我的補(bǔ)充

法則 #3 和 #4,大多數(shù)情況都非常容易理解,有幾種情況需要特別注意,

函數(shù)嵌套
需要注意的是object對(duì)象中的函數(shù)內(nèi)部再次嵌套函數(shù)的情況,

var name = "windows";  
      
var obj = {  

    name:"object",  

    f1:function(){  

      console.log("this: "+this.name)

      function f2(){  

            console.log("this: " + this.name)
      }

      f2();  
    }  
};  

執(zhí)行

> obj.f1();
 this: object
 this: windows

可以看到,在運(yùn)行期,被調(diào)用函數(shù) f1() 中的this指向 obj_,而被調(diào)用函數(shù) _f2() 中的this指向的是 windows ( global object );因?yàn)?f1 函數(shù)在當(dāng)前的運(yùn)行時(shí)中是通過(guò) obj.f1() 進(jìn)行的關(guān)聯(lián)調(diào)用,所以,根據(jù)定義 #3,在當(dāng)前的運(yùn)行期間,_f1()_ 內(nèi)部的 this 是指向 obj 對(duì)象的( 通過(guò)將 obj 的引用直接賦值給 this ),而, f2 函數(shù)在運(yùn)行期是沒(méi)有與其它 object 進(jìn)行關(guān)聯(lián)調(diào)用,所以,在當(dāng)前的運(yùn)行時(shí)期,_f2_ 是一個(gè) standalone 的函數(shù),所以,根據(jù)定義 #4,在當(dāng)前的運(yùn)行期間,_f2()_ 的內(nèi)部this是指向 windows 的。(注意,這里我反復(fù)強(qiáng)調(diào)當(dāng)前運(yùn)行期間,是因?yàn)?b>this是在運(yùn)行時(shí)被賦值的,所以,要特別注意的是,即使某個(gè)函數(shù)的定義不變,但在不同的執(zhí)行環(huán)境(運(yùn)行環(huán)境)中,this是會(huì)發(fā)生變化;)

回調(diào)函數(shù)
參看函數(shù)回調(diào)場(chǎng)景-1和函數(shù)回調(diào)場(chǎng)景-2

函數(shù)賦值
參看將函數(shù)賦值-standalone以及相關(guān)變種章節(jié)

可見(jiàn),要判斷this運(yùn)行期到底指的是什么,并沒(méi)有那么容易,但是,只要牢牢的把握好兩點(diǎn),就可以迎刃而解,

this運(yùn)行期相關(guān)的
更確切的說(shuō),this是在運(yùn)行期被賦值的,所以,它的值是在運(yùn)行期動(dòng)態(tài)確定的。

this是否與其它對(duì)象關(guān)聯(lián)調(diào)用
這里的關(guān)聯(lián)調(diào)用指的是 javascript 的一種語(yǔ)法,既是調(diào)用語(yǔ)句顯式的寫(xiě)為obj.func(),另外需要注意的是,_javascript_ 方法的調(diào)用不會(huì)隱式的隱含 this。只要沒(méi)有顯式的關(guān)聯(lián)調(diào)用,那么就是standalone的調(diào)用,就符合法則 #4,所以,this指向 _Global Object_。

this 的 Object

注意,this定義中所指的Object指的是 javascriptObject 類型,既是通過(guò)

var o1 = {};
var o2  = new Object();
var o3 = Object.create(Object.prototype);

這樣的方式構(gòu)建出來(lái)的對(duì)象;

備注,最開(kāi)始,自己有個(gè)思維的誤區(qū),認(rèn)為既然 javascript 一切皆為對(duì)象,那么this指針是指向對(duì)象的,那么是不是也可以指向Function,Number等對(duì)象?答案是否定的。

起初,我是按照上面的邏輯來(lái)理解的,直到當(dāng)我總結(jié)到bind 是如何實(shí)現(xiàn)的小節(jié)后,發(fā)現(xiàn)Function對(duì)象在調(diào)用方法屬性bind的時(shí)候,bind方法內(nèi)部的this指向的是Function,這才恍然大悟,thisObject實(shí)際上是可以指向任何 javascript Object的,包括 Object_、_Function 等。

this 是變化的

我們來(lái)看這樣一個(gè)例子,

var C = "王麻子";

var A = {
  name: "張三",
  describe: function () {
    return "姓名:"+ this.name;
  }
};

var B = {
  name: "李四"
};

// 執(zhí)行,
> A.describe();
  "張三"

> B.describe = A.describe;
> B.describe()
  "李四"

> var describe = A.describe;
> describe();
  "王麻子"

可以看到,雖然 A.describe 方法的定義不變,但是其運(yùn)行時(shí)環(huán)境發(fā)生了變化,_this_ 的指向也就發(fā)生了變化。

> B.describe = A.describe;
> B.describe()
  "李四"

在運(yùn)行時(shí),相當(dāng)于運(yùn)行的是 B 的 describe 方法

> var describe = A.describe;
> describe();
  "王麻子"

在運(yùn)行時(shí),相當(dāng)于運(yùn)行的是 windows 的 describe 方法

方法調(diào)用沒(méi)有隱含 this

經(jīng)常寫(xiě) Java 代碼的原因,經(jīng)常會(huì)習(xí)慣性的認(rèn)為只要在對(duì)象方法里面調(diào)用某個(gè)方法或者屬性,隱含了 this,比如

public class Person{

  String name;

  public String getName(){
    return name;
  }

  public String getName2(){
    return this.name;
  }

}

而 Javascript 實(shí)際上并沒(méi)有這種隱含的表達(dá)方式;詳細(xì)驗(yàn)證過(guò)程參考將函數(shù)賦值-standalone

關(guān)聯(lián)調(diào)用 - 容易混淆的場(chǎng)景

從this 是什么章節(jié)中,為了方便對(duì) #3 進(jìn)行描述,我起了個(gè)名字叫做 關(guān)聯(lián)調(diào)用 ;那么有些情況看似是 _關(guān)聯(lián)調(diào)用_,實(shí)則不然;

我們有一個(gè)標(biāo)準(zhǔn)的對(duì)象,定義如下,

var name = "windows";
var obj = {
  name: "obj",
  foo: function () {
    console.log("this: "+ this.name);
  }
};

通過(guò)標(biāo)準(zhǔn)的 關(guān)聯(lián)調(diào)用 的方式,我們進(jìn)行如下的調(diào)用,

> obj.foo() 
  "this: obj"

根據(jù)法則 #3 既 關(guān)聯(lián)調(diào)用 的定義,得到 this -> obj_;如果事事都如此的簡(jiǎn)單,如此的標(biāo)準(zhǔn),那可就好了,總會(huì)有些讓人費(fèi)解的情況,現(xiàn)在來(lái)看看如下的一些特殊的例子,加深對(duì) _關(guān)聯(lián)調(diào)用 的理解。

將函數(shù)賦值 - standalone
> var fooo = obj.foo
> fooo();
  "this: windows"

輸出的 windows_,既是 _this -> global object_,而不是我們期望的 _obj_;為什么?原因是,_obj.foo 其實(shí)是 foo 函數(shù)的函數(shù)地址,通過(guò) var fooo = obj.foo 將該函數(shù)的地址賦給了變量 _fooo_,那么當(dāng)執(zhí)行

> fooo();

的時(shí)候,fooo() 執(zhí)行的是是一個(gè)standalone的方法,根據(jù)法則 #4,所以該方法內(nèi)部的this指向的是 Global Object_;注意,_obj.foo 表示函數(shù) foo 的入口地址,所以,變量 fooo 等價(jià)與 foo 函數(shù)。

備注:由于受到寫(xiě) Java 代碼習(xí)慣的原因,很容易將這里解釋為默認(rèn)執(zhí)行的是this.fooo(),_fooo()_ 的調(diào)用隱含了this,因此就會(huì)想到,由于this指向的 Global Object_,所以這里當(dāng)然返回的就是this: windows;但是,這樣解釋,是不對(duì)的,因?yàn)?_Javascript 壓根沒(méi)有這種隱含this的概念,參看用例,

var name = "windows";

var o = {

  name : "o",

  f2 : function(){
      console.log( "o -> f2");
      console.log( "this: "this.name );
  },

  f : function(){

      console.log("f.this -> " + this.name);

      var f2 = function(){
          console.log( "f -> f2");
          console.log( this.name );
      }

      f2(); // f -> f2

      this.f2(); // o -> f2

  }

}

可以看到,在 o.f() 函數(shù)中,如果 f2() 的調(diào)用隱含了this,那么 f2()this.f2() 兩者調(diào)用應(yīng)該是等價(jià)的;但是,在實(shí)際執(zhí)行過(guò)程中,_f2()_ 和 this.f2() 執(zhí)行的是兩個(gè)截然不同的方法,因此 f2()this.f2()_,所以 _f2() 并沒(méi)有隱示的表示為 _this.f2()_;

將函數(shù)賦值變種 - 匿名 standalone 函數(shù)立即執(zhí)行
> (obj.foo = obj.foo)() 
  "this: windows"

首先,立即執(zhí)行 foo 函數(shù),然后將 foo 函數(shù)賦值給對(duì)象 obj 對(duì)象的 foo 屬性;等價(jià)于執(zhí)行如下的代碼,

var name = "windows";    
var obj = { name : "obj" };
(obj.foo = function () {
  console.log("this: " + this.name);
})();

輸出,

"this: windows"

可以看到,_this_ -> _global object_,這里為什么指向的是 _global object_?其實(shí)這里的立即執(zhí)行過(guò)程,就是執(zhí)行的如下代碼,

(function () {
  console.log("this: " + this.name);
}());

由此可以看出,實(shí)際上進(jìn)行一個(gè)匿名函數(shù)的立即執(zhí)行;也就是說(shuō)執(zhí)行過(guò)程中并沒(méi)有使用 關(guān)聯(lián)調(diào)用_,而是一次 _standalone 函數(shù)的自身調(diào)用,所以根據(jù)法則 #4,_this_ -> _global object_。執(zhí)行完以后,將該匿名函數(shù)賦值給 _obj.foo_。

再次執(zhí)行,

> obj.foo();
 "this: obj"

這次執(zhí)行的過(guò)程是一次標(biāo)準(zhǔn)的 關(guān)聯(lián)調(diào)用 過(guò)程,所以根據(jù)法則 #3,_this_ -> _obj_。

作為判斷條件 - 匿名函數(shù)立即執(zhí)行
> (false || obj.foo)() 
  "windows"

等價(jià)于執(zhí)行,

(false || function () {
  console.log("this: " + this.name);
})()

原理和函數(shù)賦值變種-匿名 standalone 函數(shù)立即執(zhí)行 一致,等價(jià)于立即執(zhí)行如下的匿名函數(shù)

(function () {
  console.log("this: " + this.name);
})()

其實(shí),把這個(gè)例子再做一個(gè)細(xì)微的更改,其中邏輯就看得更清楚了,為 foo 函數(shù)添加一個(gè)返回值 return true

var name = "windows";
var obj ={
  name: "obj",
  foo: function () {
    console.log("this: "+ this.name);
    return true;
  }
};

再次執(zhí)行,

> (false || obj.foo)() 
  "windows"
  true

可見(jiàn),_obj.foo_ 函數(shù)執(zhí)行以后,返回 _true_。上述代碼其實(shí)等價(jià)于執(zhí)行如下的代碼,

(false || function () {
  console.log("this: " + this.name);
  return true;
})()
函數(shù)回調(diào)場(chǎng)景 0 - 基本原理
var counter = {
  count: 0,
  inc: function () {
    "use strict";
    this.count++;
  }
};

function callIt(callback) {
  callback();
}

> callIt(counter.inc)
  TypeError: Cannot read property "count" of undefined

可以看到,把一個(gè)定義有this關(guān)鍵字的函數(shù)作為其它函數(shù)的回調(diào)函數(shù),是危險(xiǎn)的,因?yàn)?b>this在運(yùn)行期會(huì)被重新賦值,上述例子很直觀的描述了這一點(diǎn),之所以報(bào)錯(cuò),是因?yàn)?b>this指向了 _Global Object_。要解決這樣的問(wèn)題,可以使用bind,調(diào)用的時(shí)候改為

> callIt(counter.inc.bind(counter))
  1
函數(shù)回調(diào)場(chǎng)景 1 - setTimeout
var name = "Bob";  
var nameObj ={  
    name : "Tom",  
    showName : function(){  
        console.log(this.name);  
    },  
    waitShowName : function(){  
        setTimeout(this.showName, 1000);  
    }  
};  

// 執(zhí)行,

> nameObj.waitShowName();
  "Tom"
  undefined

setTimeout(this.showName, 1000);nameObj.showName 函數(shù)作為回調(diào)函數(shù)參數(shù)傳遞給 setTimeout_;那么為什么當(dāng) _setTimeout 執(zhí)行回調(diào)的時(shí)候,_nameObj.showName_ 方法返回的是 undefined 呢?為什么不是返回全局對(duì)象對(duì)應(yīng)的 name Bob_?原因只有一個(gè),那就是 _setTimeout 有自己的 this 對(duì)象,而它沒(méi)有 name 屬性,而在回調(diào) showName 函數(shù)的時(shí)候,_showName_ 函數(shù)中的 this 正是 setTimeout 上下文中的 this_,而該 _this 并沒(méi)有定義 name 屬性,所以這里返回 _undefined_。

函數(shù)回調(diào)場(chǎng)景 2 - DOM 對(duì)象
var o = new Object();

o.f = function () {
  console.log(this === o);
}

o.f() // true,得到期望的結(jié)果 this -> o

但是,如果將f方法指定給某個(gè)click事件,this的指向發(fā)生了改變,

$("#button").on("click", o.f);

點(diǎn)擊按鈕以后,返回的是false,是因?yàn)樵趫?zhí)行過(guò)程中,this不再指向?qū)ο?b>o了而改為指向了按鈕的DOM對(duì)象了;Sounds Good,但問(wèn)題是,怎么被改動(dòng)的?看了一下 jQuery 的源碼,_event.js_,摘錄重要的片段如下,

function on( elem, types, selector, data, fn, one ) {
  .......
  if ( one === 1 ) {
    origFn = fn;
    fn = function( event ) {

      // Can use an empty set, since event contains the info
      jQuery().off( event );
      return origFn.apply( this, arguments );
    };

    // Use same guid so caller can remove using origFn
    fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
  }
  .......
}

o.f 函數(shù)的地址賦值給 fn 參數(shù),_fn_ -> origFn_,最后是通過(guò)origFn.apply( this, arguments );來(lái)調(diào)用 _o.f 函數(shù)的,而這里的 this 就是當(dāng)前的 DOM 對(duì)象,既是這個(gè)按鈕 button_;通過(guò)這樣的方式,在執(zhí)行過(guò)程中,通過(guò)回調(diào)函數(shù) _$("button").on(...) 成功的將新的 this 對(duì)象 button 注入了 o.f 函數(shù)。那么如何解決呢?參看function.prototype.apply())
的小節(jié)#3,動(dòng)態(tài)綁定回調(diào)函數(shù)。

函數(shù)回調(diào)場(chǎng)景 3 - 數(shù)組對(duì)象方法的回調(diào)
var obj = {
  name: "張三",
  times: [1, 2, 3],
  print: function () {
    this.times.forEach(function (n) {
      console.log(this.name);
    });
  }
};

> obj.print();
  "undefined"
  "undefined"
  "undefined"

這里我們期望的是,依次根據(jù)數(shù)組 times 的長(zhǎng)度,輸出 obj.name 三次,但是實(shí)際運(yùn)行結(jié)果是,數(shù)組雖然循環(huán)了三次,但是每次輸出都是 _undefined_,那是因?yàn)槟涿瘮?shù)

function(n){
  console.log(this.name);
}

作為數(shù)組 times 的方法 forEach 的回調(diào)函數(shù)執(zhí)行,在 forEach 方法內(nèi)部該匿名函數(shù)必然是作為 standalone 方法執(zhí)行的,所以,this指向了 _Global Object_;

進(jìn)一步,為什么“在 forEach 方法內(nèi)部該匿名函數(shù)必然是作為 standalone 方法執(zhí)行的”?為什么必然是作為 standalone 方法執(zhí)行?是因?yàn)椴荒茉?forEach 函數(shù)中使用 this.fn() 的方式來(lái)調(diào)用該匿名回調(diào)函數(shù)( fn 作為參數(shù)引用該匿名回調(diào)函數(shù) ),因?yàn)槿绻@樣做,在運(yùn)行時(shí)期會(huì)報(bào)錯(cuò),因?yàn)樵?forEach 函數(shù)的 this 對(duì)象中找不到 fn 這樣的屬性,而該 this 對(duì)象指向的是 obj.times 數(shù)組對(duì)象。因此,得到結(jié)論“在 forEach 方法內(nèi)部該匿名函數(shù)必然是作為 standalone 方法執(zhí)行的”

解決辦法,使用 bind

obj.print = function () {
  this.times.forEach(function (n) {
    console.log(this.name);
  }.bind(this));
};

> obj.print()
  "張三"
  "張三"
  "張三"    

obj 對(duì)象作為 this 綁定到該匿名函數(shù)上,然后再作為回調(diào)函數(shù)參數(shù)傳遞給 forEach 函數(shù),這樣,在 forEach 函數(shù)中,用 standalone 的方式調(diào)用 fn 的時(shí)候,_fn_ 中的 this 指向的就是數(shù)組對(duì)象 obj 對(duì)象,這樣,我們就能順利的輸出 obj.name 了。

綁定 this

有上述描述可知,this的值在運(yùn)行時(shí)根據(jù)不同上下文環(huán)境有不同的值,因此我們說(shuō)this的值是變化的,這就給我們的編程帶來(lái)了麻煩,有時(shí)候,我們期望,得到一個(gè)固定的this。Javascript 提供了callapply以及bind這三個(gè)方法,來(lái)固定this的指向;這三個(gè)方法存儲(chǔ)在 function.prototype 域中,

function.prototype.call()

總結(jié)起來(lái),就是解決函數(shù)在調(diào)用的時(shí)候,如何解決this動(dòng)態(tài)變化的問(wèn)題。

調(diào)用格式,

func.call(thisValue, arg1, arg2, ...)

第一個(gè)參數(shù)是在運(yùn)行時(shí)用來(lái)賦值給 func 函數(shù)內(nèi)部的 this 的。

通過(guò)f.call(obj)的方式調(diào)用函數(shù),在運(yùn)行時(shí),將 obj 賦值給 _this_;

var obj = {};

var f = function () {
  return this;
};

f() === this // true
f.call(obj) === obj // true

call方法的參數(shù)是一個(gè)對(duì)象,如果參數(shù)為 空_、_null 或者 _undefined_,則使用默認(rèn)的全局對(duì)象;

var n = 123;
var obj = { n: 456 };

function a() {
  console.log(this.n);
}

> a.call() 
  123
> a.call(null) 
  123
> a.call(undefined) 
  123
> a.call(window) 
  123
> a.call(obj) 
  456

如果call方法的參數(shù)是一個(gè)原始值,那么這個(gè)原始值會(huì)自動(dòng)轉(zhuǎn)成對(duì)應(yīng)的包裝對(duì)象,然后賦值給 this

var f = function () {
  return this;
};

> f.call(5)
  [Number: 5]

call方法可以接受多個(gè)參數(shù),第一個(gè)參數(shù)就是賦值給 this 的對(duì)象,

var obj = {
    name : "obj"
}

function add(a, b) {
  console.log(this.name);
  return a + b;
}

> add.call(obj, 1, 2) 
  obj
  3

call方法可以調(diào)用對(duì)象的原生方法;

var obj = {};
obj.hasOwnProperty("toString") // false

// “覆蓋”掉繼承的 hasOwnProperty 方法
obj.hasOwnProperty = function () {
  return true;
};
obj.hasOwnProperty("toString") // true

Object.prototype.hasOwnProperty.call(obj, "toString") // false

方法 hasOwnProperty 是對(duì)象 objObject.prototype 中繼承的方法,如果一旦被覆蓋,就不會(huì)得到正確的結(jié)果,那么,我們可以使用call的方式調(diào)用原生方法,將 obj 作為 this 在運(yùn)行時(shí)調(diào)用,這樣,變通的,我們就可以調(diào)用 obj 對(duì)象所繼承的原生方法了。

function.prototype.apply()

總結(jié)起來(lái),和call一樣,就是解決函數(shù)在調(diào)用的時(shí)候,如何解決this動(dòng)態(tài)變化的問(wèn)題。

apply方法的作用與call方法類似,也是改變this指向,然后再調(diào)用該函數(shù)。唯一的區(qū)別就是,它接收一個(gè)數(shù)組作為函數(shù)執(zhí)行時(shí)的參數(shù),使用格式如下。
func.apply(thisValue, [arg1, arg2, ...])
apply方法的第一個(gè)參數(shù)也是this所要指向的那個(gè)對(duì)象,如果設(shè)為null或undefined,則等同于指定全局對(duì)象。第二個(gè)參數(shù)則是一個(gè)數(shù)組,該數(shù)組的所有成員依次作為參數(shù),傳入原函數(shù)。

原函數(shù)的參數(shù),在call方法中必須一個(gè)個(gè)添加,但是在apply方法中,必須以數(shù)組形式添加

function f(x,y){
  console.log(x+y);
}

f.call(null,1,1) // 2
f.apply(null,[1,1]) // 2

找出數(shù)組最大的元素

var a = [10, 2, 4, 15, 9];
Math.max.apply(null, a)
// 15

將數(shù)組的空元素變?yōu)?undefined

Array.apply(null, ["a",,"b"])
// [ "a", undefined, "b" ]

空元素undefined的差別在于,數(shù)組的forEach方法會(huì)跳過(guò)空元素,但是不會(huì)跳過(guò)undefined。因此,遍歷內(nèi)部元素的時(shí)候,會(huì)得到不同的結(jié)果。

 var a = ["a", , "b"];

 function print(i) {
   console.log(i);
 }

 a.forEach(print)
 // a
 // b

 Array.apply(null, a).forEach(print)
 // a
 // undefined
 // b   

綁定回調(diào)函數(shù)的對(duì)象
函數(shù)回調(diào)場(chǎng)景-2我們看到this被動(dòng)態(tài)的更改為了 DOM 對(duì)象 _button_,這往往不是我們所期望的,所以,我們可以再次綁定回調(diào)函數(shù)來(lái)固定this,如下,

 var o = new Object();

 o.f = function () {
   console.log(this === o);
 }

 var f = function (){
   o.f.apply(o);
   // 或者 o.f.call(o);
 };

 $("#button").on("click", f);

這樣,我們用 f 函數(shù)封裝原來(lái)的回調(diào)函數(shù) o.f_,并使用apply方法固定住this,使其永遠(yuǎn)指向 _object o,這樣,就達(dá)到了this不被動(dòng)態(tài)修改的目的。

function.prototype.bind()

總結(jié)起來(lái),其實(shí)就是在把函數(shù)作為參數(shù)傳遞的時(shí)候,如何解決this動(dòng)態(tài)變化的問(wèn)題。

解決的問(wèn)題

在認(rèn)識(shí)關(guān)聯(lián)調(diào)用 - 容易混淆的場(chǎng)景中,我們濃墨重彩的描述了將函數(shù)賦值以后,導(dǎo)致this在運(yùn)行期發(fā)生變化的種種場(chǎng)景,而且在編程過(guò)程當(dāng)中,也是非常容易導(dǎo)致問(wèn)題的場(chǎng)景;那么有沒(méi)有這么一種機(jī)制,即便是在函數(shù)賦值后,在運(yùn)行期依然能夠保護(hù)并固定住我的this?答案是有的,那就是bind。下面,我們來(lái)看一個(gè)例子,

var d = new Date();
d.getTime() // 1481869925657

我們使用語(yǔ)句 d.getTime() 通過(guò)對(duì)象 d 關(guān)聯(lián)調(diào)用函數(shù) getTime()_,根據(jù)法則 #3,函數(shù) _getTime() 內(nèi)部的 this 指向的是對(duì)象 d_,然后從 _d 對(duì)象中成功獲取到了時(shí)間。但是,我們稍加改動(dòng),將對(duì)象 d 中的函數(shù) getTime 賦值給另外一個(gè)變量,在執(zhí)行呢?

var print = d.getTime;
print() // Uncaught TypeError: this is not a Date object.

Wow~, 畫(huà)風(fēng)突變,得不到時(shí)間了,而且還拋出了一個(gè)程序異常,好玩,你的程序因此崩潰.. 這就是this在執(zhí)行期動(dòng)態(tài)變化所導(dǎo)致的,當(dāng)我們將函數(shù) d.getTime 賦值給 print_,然后語(yǔ)句 _print() 表示將函數(shù) getTime 作為 standalone 的函數(shù)在運(yùn)行期調(diào)用,所以,內(nèi)部的this發(fā)生變化,指向了 _Global Object_,也因此,我們得不到時(shí)間了,但我們得到一個(gè)意想不到的異常..

Ok, 別怕,孩子,bind登場(chǎng)了,

var print = d.getTime.bind(d);
print() // 148186992565

賦值過(guò)程中_,將函數(shù)通過(guò)bind語(yǔ)法綁定this對(duì)象 _d 以后,再賦值給一個(gè)新的變量;這樣,即便 print() 再次作為 standalone 的函數(shù)在運(yùn)行期調(diào)用,this的指向也不再發(fā)生變化,而是固定的指向了對(duì)象 _d_。

bind 是如何實(shí)現(xiàn)的
if(!("bind" in Function.prototype)){
  Function.prototype.bind = function(){
    var fn = this; // 當(dāng)前調(diào)用 bind 的當(dāng)前對(duì)象 fn ( fn.bind(..) )
    var context = arguments[0]; // 用來(lái)綁定 this 對(duì)象的參數(shù)
    var args = Array.prototype.slice.call(arguments, 1);
    var fnbound = function(){
      return fn.apply(context, args);
    }
    return fnbound;
  }
}

Function對(duì)象的prototype原型中新增一個(gè)屬性bind,該bind是一個(gè) function 函數(shù);這里要特別特別注意,每次bind調(diào)用以后,返回的是一個(gè)新的function,

    var fnbound = function(){
      return fn.apply(context, args);
    }
    return fnbound;

通過(guò) fnbound 函數(shù)套一層原函數(shù) fn 作為閉包,然后返回這個(gè)新的 function _fnbound_;大部分教程就是這樣介紹即止了;其實(shí),我想問(wèn)的是,為什么bind要這么設(shè)計(jì),直接返回fn.apply(context, args);不是挺好嗎?為什么還要在外面套一層新函數(shù) _fnbound_?Ok,這里我就來(lái)試圖解釋下原因吧;

采用反證法,如果,我們不套這么一層新函數(shù) _fubound_,看看,會(huì)怎樣?于是,我們得到如下的實(shí)現(xiàn),

if(!("bind" in Function.prototype)){
  Function.prototype.bind = function(){
    var fn = this; // 當(dāng)前調(diào)用 bind 的當(dāng)前對(duì)象 fn ( fn.bind(..) )
    var context = arguments[0]; // 用來(lái)綁定 this 對(duì)象的參數(shù)
    var args = Array.prototype.slice.call(arguments, 1);
    return fn.apply(context, args);
  }
}

直接返回fn.apply(context, args),oh,頓時(shí),我明白了,fn.apply(...)這是一條執(zhí)行命令啊,它會(huì)立即執(zhí)行 fn_,將 _fn 執(zhí)行的結(jié)果返回.. 而我們這里的bind的初衷只是擴(kuò)充 fn 函數(shù)的行為(既綁定this對(duì)象),然后返回一個(gè)函數(shù)的引用,而正式因?yàn)槲覀儫o(wú)法在綁定以后,直接返回原有函數(shù)的引用,所以,這里,我們才需要?jiǎng)?chuàng)建一個(gè)新的函數(shù)并返回這個(gè)新的函數(shù)的引用,已達(dá)到bind的設(shè)計(jì)目的。Ok,這下總算是清楚了。

特性
綁定匿名函數(shù)
obj.print = function () {
  this.times.forEach(function (n) {
    console.log(this.name);
  }.bind(this));
};

可見(jiàn),我們可以直接改匿名函數(shù)執(zhí)行bind,然后在將其賦值給某個(gè)對(duì)象;更詳細(xì)的用例參考函數(shù)回調(diào)場(chǎng)景 3 - 數(shù)組對(duì)象方法的回調(diào)

作為函數(shù)直接調(diào)用
var altwrite = document.write;
altwrite("hello"); 

在瀏覽器運(yùn)行這個(gè)例子,得到錯(cuò)誤Uncaught ReferenceError: alwrite is not defined,這個(gè)錯(cuò)誤并沒(méi)有真正保留底層的原因,真正的原因是,_document_ 對(duì)象的 write 函數(shù)再執(zhí)行的時(shí)候,內(nèi)部this指向了 Global Object

為了解決上述問(wèn)題,我們可以bind document 對(duì)象,

altwrite.bind(document)("hello")

注意這里的寫(xiě)法,altwrite.bind(document)返回的是一個(gè)Function,所以可以直接跟參數(shù)調(diào)用。

綁定函數(shù)參數(shù)

除了綁定this對(duì)象意外,還可以綁定函數(shù)中的參數(shù),看如下的例子,

var add = function (x, y) {
  return x * this.m + y * this.n;
}

var obj = {
  m: 2,
  n: 2
};

var newAdd = add.bind(obj, 5);

newAdd(5);
// 20

add.bind(obj, 5);除了綁定 add 函數(shù)的this對(duì)象為 obj 以外,將其固定obj 以外,還綁定了 add 函數(shù)的第一個(gè)參數(shù) x_,并將其固定為 _5_;這樣,得到的 _newAdd 函數(shù)只能接收一個(gè)參數(shù),那就是 y 了,因?yàn)?x 已經(jīng)被bind綁定且固定了,所以可以看到,隨后執(zhí)行的語(yǔ)句newAdd(5)傳遞的實(shí)際上是 y 參數(shù)。

若綁定 null 或者 undefined

如果bind方法的第一個(gè)參數(shù)是 null 或 _undefined_,等于將this綁定到全局對(duì)象,函數(shù)運(yùn)行時(shí)this指向 _Global Object_。

var name = "windows";

function add(x, y) {
  console.log(this.name);
  return x + y;
}

var plus = add.bind(null, 5); // 綁定了 x 參數(shù)

> plus(10) // 賦值的是 y 參數(shù),于是執(zhí)行的是 5 + 10
  "windows"
  15
改寫(xiě)原生方法的使用方式

首先,

> [1, 2, 3].push(4)
  4 // 輸出新增后數(shù)組的長(zhǎng)度

等價(jià)于

Array.prototype.push.call([1, 2, 3], 4)

第一個(gè)參數(shù) [1, 2, 3] 綁定 push 函數(shù)的this關(guān)鍵字,第二個(gè)參數(shù) _4_,是需要被添加的值。

補(bǔ)充一下

為什么說(shuō)這里是等價(jià)的?我們來(lái)解讀一下

> [1, 2, 3].push(4)
  4 // 輸出新增后數(shù)組的長(zhǎng)度

的執(zhí)行過(guò)程,_[1, 2, 3]_ 作為數(shù)組對(duì)象,調(diào)用其原型中的 Array.prototype.push 方法,很明顯,采用的是關(guān)聯(lián)調(diào)用,因此 push 函數(shù)內(nèi)部的 this 指向的是數(shù)組對(duì)象 _[1, 2, 3]_;而這里,我們通過(guò)

Array.prototype.push.call([1, 2, 3], 4)

這樣的調(diào)用方式,只是換湯不換藥,同樣是執(zhí)行的數(shù)組中的原型方法 _push_,只是this的傳遞方式不同而已,這里是通過(guò)bind直接將this賦值為數(shù)組對(duì)象 _[1, 2, 3]_,而不是通過(guò)之前的關(guān)聯(lián)調(diào)用;所以,兩種調(diào)用方式是等價(jià)的。

補(bǔ)充完畢

再次,

call 方法調(diào)用的是 Function 對(duì)象的原型方法既 Function.prototype.call(...)_,那么我們?cè)賮?lái)將它 _bind 一下,看看會(huì)有什么結(jié)果

> var push = Function.prototype.call.bind(Array.prototype.push);

> push([1, 2, 3], 4);
  4 // 返回?cái)?shù)組長(zhǎng)度

// 或者寫(xiě)為

> var a = [1, 2, 3];
> push(a, 4);
  4
> a
  [1, 2, 3, 4]

我們得到了一個(gè)具備數(shù)組 push 操作的一個(gè)新的函數(shù) push(...) ( 注: bind 每次回返回一個(gè)新的函數(shù) );

那是為什么呢?

可以看到,背后的核心是,

push([1, 2, 3], 4);

等價(jià)于執(zhí)行

Array.prototype.push.call([1, 2, 3], 4)

所以,我們得證明Function.prototype.call.bind(Array.prototype.push)([1, 2, 3], 4)Array.prototype.push.call([1, 2, 3], 4)兩個(gè)函數(shù)的執(zhí)行過(guò)程是等價(jià)的( 注意,為什么比較的是執(zhí)行過(guò)程等價(jià),因?yàn)?b>call函數(shù)是立即執(zhí)行的,而bind返回的是一個(gè)函數(shù)引用,所以必須比較兩者的執(zhí)行過(guò)程 );其實(shí),要證明這個(gè)問(wèn)題,最直接方法就是去查看函數(shù)Function.prototype.call的源碼,可惜,我在官網(wǎng) MDN Function.prototype.call() 上面也沒(méi)有看到源碼;那么這里,其實(shí)可以做一些推理,

Function.prototype.call.bind(Array.prototype.push)([1, 2, 3], 4)

通過(guò)bind,這里返回一個(gè)新的 call 函數(shù),該函數(shù)綁定了 Array.prototype.push Function 對(duì)象做為其this對(duì)象;那么Function.prototype.call函數(shù)內(nèi)部會(huì)怎么執(zhí)行呢?我猜想應(yīng)該就是執(zhí)行this.apply(context, params)之類的,this表示的是 Array.prototype.push_,context表示的既是這里的數(shù)組對(duì)象 _[1, 2, 3]_, params表示的既是這里的參數(shù) _4

Array.prototype.push.call([1, 2, 3], 4)
同理,由上述Function.prototype.call函數(shù)內(nèi)部的執(zhí)行過(guò)程是執(zhí)行this.apply(context, params)的推斷來(lái)看,this依然是指向的 Array.prototype.push_,context表示的既是這里的數(shù)組對(duì)象 _[1, 2, 3]_, params表示的既是這里的參數(shù) _4_;所以,這里的調(diào)用方式與 _Function.prototype.call.bind(Array.prototype.push)([1, 2, 3], 4) 的方式等價(jià);所以,我們得出如下結(jié)論,
Array.prototype.push.call([1, 2, 3], 4) <=> Function.prototype.call.bind(Array.prototype.push)([1, 2, 3], 4) <=> push([1, 2, 3], 4)

使用 bind 的一些注意事項(xiàng)
每次返回一個(gè)新函數(shù)

bind方法每運(yùn)行一次,就返回一個(gè)新函數(shù),這會(huì)產(chǎn)生一些問(wèn)題。比如,監(jiān)聽(tīng)事件的時(shí)候,不能寫(xiě)成下面這樣。

element.addEventListener("click", o.m.bind(o));

上面代碼中,click 事件綁定bind方法新生成的一個(gè)匿名函數(shù)。這樣會(huì)導(dǎo)致無(wú)法取消綁定,所以,下面的代碼是無(wú)效的。

element.removeEventListener("click", o.m.bind(o));

正確的方法是寫(xiě)成下面這樣,使得 addremove 使用的是同一個(gè)函數(shù)的引用。

var listener = o.m.bind(o);
element.addEventListener("click", listener);
//  ...
element.removeEventListener("click", listener);
use strict

使用嚴(yán)格模式,該部分可以參考阮一峰的教程嚴(yán)格模式,說(shuō)得非常詳細(xì);不過(guò)應(yīng)用到面向?qū)ο缶幊汤锩妫饕褪菫榱吮苊?b>this在運(yùn)行期動(dòng)態(tài)指向 _Global Object_,如果發(fā)生這類的情況,報(bào)錯(cuò);例如

function f() {
  "use strict";
  this.a = 1;
};

f();// 報(bào)錯(cuò),this未定義

當(dāng)執(zhí)行過(guò)程中,發(fā)現(xiàn)函數(shù) f 中的this指向了 _Global Object_,則報(bào)錯(cuò)。

構(gòu)造函數(shù)中的 this this -> Object.prototype instance

構(gòu)造函數(shù)比較特別,_javascript_ 解析過(guò)程不同于其它普通函數(shù);

假如我們有如下的構(gòu)造函數(shù),

var Person = function(name, age){
   this.name = name;
   this.age = age;
}

當(dāng) javascript 語(yǔ)法解析器解析到如下語(yǔ)句以后,

var p = new Person("張三", 35);

實(shí)際上執(zhí)行的是,

function new( /* 構(gòu)造函數(shù) */ constructor, /* 構(gòu)造函數(shù)參數(shù) */ param1 ) {
  // 將 arguments 對(duì)象轉(zhuǎn)為數(shù)組
  var args = [].slice.call(arguments);
  // 取出構(gòu)造函數(shù)
  var constructor = args.shift();
  // 創(chuàng)建一個(gè)空對(duì)象,繼承構(gòu)造函數(shù)的 prototype 屬性
  var context = Object.create(constructor.prototype);
  // 執(zhí)行構(gòu)造函數(shù)
  var result = constructor.apply(context, args);
  // 如果返回結(jié)果是對(duì)象,就直接返回,則返回 context 對(duì)象
  return (typeof result === "object" && result != null) ? result : context;
}

備注:_arguments_ 可表示一個(gè)函數(shù)中所有的參數(shù),也就是一個(gè)函數(shù)所有參數(shù)的結(jié)合。

下面,我們一步一步的來(lái)分析該構(gòu)造函數(shù)的實(shí)現(xiàn),弄清楚this指的是什么,

constructor

就是 Person 構(gòu)造函數(shù),

context

var context = Object.create(constructor.prototype);通過(guò) constructor.prototype 創(chuàng)建了一個(gè)新的對(duì)象,也就是 Person.prototype 的一個(gè)實(shí)例 _Person.prototype isntance_;

constructor.apply(context, args);

注意,這步非常關(guān)鍵,_context_ 作為 constructor 構(gòu)造函數(shù)的this,所以

var Person = function(name, age){
   this.name = name;
   this.age = age;
}

中的this在執(zhí)行過(guò)程中指向的實(shí)際上就是該 context 對(duì)象。

result

constructor.apply(context, args);方法調(diào)用的返回值,我們當(dāng)前用例中,_Person_ 構(gòu)造函數(shù)并沒(méi)有返回任何東西,所以,這里是 _null_。

return (typeof result === "object" && result != null) ? result : context;

new方法的最后返回值,如果 result 不為 null_,則返回 _result 否則返回的是 context_;我們這個(gè)用例,當(dāng)初始化構(gòu)造函數(shù)完成以后,返回的是 _context 既 _Person.prototype instance_,也就是構(gòu)造函數(shù)中的this指針;這也是大多數(shù)構(gòu)造函數(shù)應(yīng)用的場(chǎng)景。

Object.prototype instance -> Object.prototype
var Obj = function (p) {
  this.p = p;
};

Obj.prototype.m = function() {
  return this.p;
};

執(zhí)行,

> var o = new Obj("Hello World!");

> o.p 
  "Hello World!"

> o.m() 
  "Hello World!"

說(shuō)實(shí)話,當(dāng)我第一次看到這個(gè)例子的時(shí)候,_o.p_ 還好理解,_o_ 就是表示構(gòu)造函數(shù) Obj 內(nèi)部的this對(duì)象,是一個(gè)通過(guò) Object.create(Obj.prototype) 得到的一份 Obj.prototype 的實(shí)例對(duì)象;但是,當(dāng)我看到 o.m 的時(shí)候,還是有點(diǎn)懵逼,_Obj.prototype_ 并不是代表的this呀,_Object.create(Obj.prototype)_ 才是( 既 Obj.prototype instance ),所以在 Obj.prototype 上定義的 m 方法,怎么可以通過(guò) o.m() 既通過(guò) Obj.prototype instance 來(lái)調(diào)用呢?( 注意,關(guān)系 o -> Object.create(Obj.prototype) -> Obj.prototype instance -> this != Obj.prototype ) 當(dāng)理解到 prototype 的涵義有,才知道,_Obj.prototype instance_ 會(huì)繼承 Obj.prototype 中的公共屬性的,所以,這里通過(guò) Obj.prototype 對(duì)象定義的 m 函數(shù)可以通過(guò) Object.prototype instance 進(jìn)行調(diào)用。

References

本文轉(zhuǎn)載自筆者的私人博客,傷神的博客,http://www.shangyang.me/2017/...
[Javascript中this關(guān)鍵字詳解](
http://www.cnblogs.com/justan...
jQuery Fundamentals Chapter - The this keyword

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/107460.html

相關(guān)文章

  • JavaScript 工廠函數(shù) vs 構(gòu)造函數(shù)

    摘要:當(dāng)談到語(yǔ)言與其他編程語(yǔ)言相比時(shí),你可能會(huì)聽(tīng)到一些令人困惑東西,其中之一是工廠函數(shù)和構(gòu)造函數(shù)。好的,讓我們用構(gòu)造函數(shù)做同樣的實(shí)驗(yàn)。當(dāng)我們使用工廠函數(shù)創(chuàng)建對(duì)象時(shí),它的指向,而當(dāng)從構(gòu)造函數(shù)創(chuàng)建對(duì)象時(shí),它指向它的構(gòu)造函數(shù)原型對(duì)象。 showImg(https://segmentfault.com/img/bVbr58T?w=1600&h=900); 當(dāng)談到JavaScript語(yǔ)言與其他編程語(yǔ)言...

    RayKr 評(píng)論0 收藏0
  • javascript基礎(chǔ):this關(guān)鍵字

    摘要:它代表函數(shù)運(yùn)行時(shí),自動(dòng)生成的一個(gè)內(nèi)部對(duì)象,只能在函數(shù)內(nèi)部使用類似的還有??偨Y(jié)關(guān)鍵字就是,誰(shuí)調(diào)用我,我就指向誰(shuí)。注意由于已經(jīng)被定義為函數(shù)內(nèi)的一個(gè)變量。因此通過(guò)關(guān)鍵字定義或者將聲明為一個(gè)形式參數(shù),都將導(dǎo)致原生的不會(huì)被創(chuàng)建。 題目 封裝函數(shù) f,使 f 的 this 指向指定的對(duì)象 。 輸入例子 bindThis(function(a, b) { return this.test +...

    LeoHsiun 評(píng)論0 收藏0
  • Javascript 深入淺出This

    摘要:中函數(shù)的調(diào)用有以下幾種方式作為對(duì)象方法調(diào)用,作為函數(shù)調(diào)用,作為構(gòu)造函數(shù)調(diào)用,和使用或調(diào)用。作為構(gòu)造函數(shù)調(diào)用中的構(gòu)造函數(shù)也很特殊,構(gòu)造函數(shù),其實(shí)就是通過(guò)這個(gè)函數(shù)生成一個(gè)新對(duì)象,這時(shí)候的就會(huì)指向這個(gè)新對(duì)象如果不使用調(diào)用,則和普通函數(shù)一樣。 this 是 JavaScript 比較特殊的關(guān)鍵字,本文將深入淺出的分析其在不同情況下的含義,可以這樣說(shuō),正確掌握了 JavaScript 中的 th...

    Y3G 評(píng)論0 收藏0
  • 理解 JavaScript 中的 this 關(guān)鍵字

    摘要:原文許多人被中的關(guān)鍵字給困擾住了,我想混亂的根源來(lái)自人們理所當(dāng)然地認(rèn)為中的應(yīng)該像中的或中的一樣工作。盡管有點(diǎn)難理解,但它的原理并不神秘。在瀏覽器中,全局對(duì)象是對(duì)象。運(yùn)算符創(chuàng)建一個(gè)新對(duì)象并且設(shè)置函數(shù)中的指向調(diào)用函數(shù)的新對(duì)象。 原文:Understanding the this keyword in JavaScript 許多人被JavaScript中的this關(guān)鍵字給困擾住了,我想混亂的...

    jayzou 評(píng)論0 收藏0
  • javascriptthis的理解

    摘要:的關(guān)鍵字總是讓人捉摸不透,關(guān)鍵字代表函數(shù)運(yùn)行時(shí),自動(dòng)生成的一個(gè)內(nèi)部對(duì)象,只能在函數(shù)內(nèi)部使用,因?yàn)楹瘮?shù)的調(diào)用場(chǎng)景不同,的指向也不同。其實(shí)只要理解語(yǔ)言的特性就很好理解。個(gè)人對(duì)中的關(guān)鍵字的理解如上,如有不正,望指正,謝謝。 javascript的this關(guān)鍵字總是讓人捉摸不透,this關(guān)鍵字代表函數(shù)運(yùn)行時(shí),自動(dòng)生成的一個(gè)內(nèi)部對(duì)象,只能在函數(shù)內(nèi)部使用,因?yàn)楹瘮?shù)的調(diào)用場(chǎng)景不同,this的指向也不...

    jimhs 評(píng)論0 收藏0
  • 理解JavaScript的核心知識(shí)點(diǎn):This

    摘要:關(guān)鍵字計(jì)算為當(dāng)前執(zhí)行上下文的屬性的值。毫無(wú)疑問(wèn)它將指向了這個(gè)前置的對(duì)象。構(gòu)造函數(shù)也是同理。嚴(yán)格模式無(wú)論調(diào)用位置,只取顯式給定的上下文綁定的,通過(guò)方法傳入的第一參數(shù),否則是。其實(shí)并不屬于特殊規(guī)則,是由于各種事件監(jiān)聽(tīng)定義方式本身造成的。 this 是 JavaScript 中非常重要且使用最廣的一個(gè)關(guān)鍵字,它的值指向了一個(gè)對(duì)象的引用。這個(gè)引用的結(jié)果非常容易引起開(kāi)發(fā)者的誤判,所以必須對(duì)這個(gè)關(guān)...

    TerryCai 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<