欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JS中this的4種綁定規(guī)則詳解

 更新時間:2020年02月04日 08:31:36   作者:Lmagic16  
如果你學過面向對象編程,那你肯定知道干什么用的,如果你沒有學過,那么暫時可以不用看這篇文章,this既不指向函數自身,也不指函數的詞法作用域,具體怎么使用JS中的this,JS中的this綁定規(guī)則又是什么?

JS中this是什么

理解this之前, 先糾正一個觀點,this 既不指向函數自身,也不指函數的詞法作用域。

如果僅通過this的英文解釋,太容易產生誤導了。

它實際是在函數被調用時才發(fā)生的綁定,也就是說this具體指向什么,取決于你是怎么調用的函數。也就是說誰調用的this,this就指向誰

JS中this說明

ES6中的箭頭函數采用的是詞法作用域。

為什么要使用this:使API設計得更簡潔且易于復用。

this即不指向自身,也不指向函數的詞法作用域。

this的指向只取決于函數的調用方式

this綁定規(guī)則

new > 顯示綁定 > 隱式綁定 > 默認綁定

默認綁定

當獨立函數調用時,不管是否在調用棧中,this都指向全局對象(瀏覽器中為window)

嚴格模式下,不能將全局對象用于默認綁定。

var a = 2;
function foo(){
  console.log(this.a);
}
function bar(){
  var a = 5;
  foo();
}
bar(); // 2

隱式綁定

當函數引用有上下文對象時,隱式綁定規(guī)則會把函數調用中的this綁定到這個上下文對象。

對象屬性引用鏈中只有最后一層在調用位置中起作用。

要求:對象內部必須包含一個指向函數的屬性,該對象可通過這個屬性間接引用函數。

function foo() {
  console.log( this.a );
}
var obj2 = {
  a: 42,
  foo: foo
};
var obj1 = {
  a: 2,
  obj2: obj2
};
obj1.obj2.foo(); // 42

隱式丟失

function foo() {
  console.log( this.a );
}
var obj = {
  a: 2,
  foo: foo
};
var bar = obj.foo; // 這里bar將引用foo函數本身,所以不帶有函數對象的上下文
var a = "oops, global"; // a是全局對象的屬性
bar(); // "oops, global"

和回調函數的情況下(參數傳遞時的隱式賦值)

function foo() {
  console.log( this.a );
}
function doFoo(fn) {
  // 參數傳遞時,相當于fn = obj.foo,就和上個例子一樣了
  fn(); // <-- call-site!
}
var obj = {
  a: 2,
  foo: foo
};
var a = "oops, global"; // `a` also property on global object
doFoo( obj.foo ); // "oops, global"

顯式綁定

采用call()和apply(),通過傳入一個對象(若為基本類型,會被封裝函數轉為對象—裝箱),將this綁定到該對象。

硬綁定

function foo() {
  console.log( this.a );
}
var obj = {
  a: 2
};
var bar = function() {
  foo.call( obj );
};
bar(); // 2
setTimeout( bar, 100 ); // 2
// 硬綁定后bar無論怎么調用,都不會影響foo函數的this綁定
bar.call( window ); // 2

硬綁定的典型應用是如下的包裹函數:

function foo(something) {
  console.log( this.a, something );
  return this.a + something;
}
var obj = {
  a: 2
};
var bar = function() {
  return foo.apply( obj, arguments ); // 將obj對象硬編碼進去
};
var b = bar( 3 ); // 2 3
console.log( b ); // 5

即將內部函數用apply硬綁定到某個對象,無論怎么調用這個包裹函數,都不會影響內部函數的this。

bind輔助函數如下:

function foo(something) {
  console.log( this.a, something );
  return this.a + something;
}
// simple `bind` helper
function bind(fn, obj) {
  return function() {
    return fn.apply( obj, arguments ); // 利用參數將obj傳入進去
  };
}
var obj = {
  a: 2
};
var bar = bind( foo, obj ); // bind( foo, obj )會返回一個包裹函數
var b = bar( 3 ); // 2 3
console.log( b ); // 5

總結:上述包裹函數,想要包裹其他函數,只能一個一個重復寫,硬編碼的方式導致不能被重用,當某種功能需要多次重復使用時,將其抽象出來,成為函數。

new綁定

任何函數都可能被用作構造函數,當函數被new操作符“構造調用”時,會執(zhí)行下面操作:

1. 創(chuàng)建一個新對象(若該函數不是JS內置的,則創(chuàng)建一個新的Object對象);

2. 將this綁定到這個對象;

3. 執(zhí)行構造函數中的代碼(為這個新對象添加屬性);

4. 若函數沒有返回其他對象,則自動返回這個新對象;若函數有return返回的是非對象,則還是自動返回這個新對象,即覆蓋那個非對象。

function foo(a) {
  this.a = a;
}
var bar = new foo( 2 );
console.log( bar.a ); // 2

補充說明

間接引用

function foo() {
  console.log( this.a );
}
var a = 2;
var o = { a: 3, foo: foo };
var p = { a: 4 };
o.foo(); // 3
(p.foo = o.foo)(); // 2,由于p.foo = o.foo的返回值是目標函數的引用,所以調用位置是foo(),而不是p.foo()或o.foo()

箭頭函數:不使用這四個this規(guī)則,根據詞法作用域來決定this。

function foo() {
  // 返回一個箭頭函數
  return (a) => {
    // `this` here is lexically adopted from `foo()`
    console.log( this.a );
  };
}
var obj1 = {
  a: 2
};
var obj2 = {
  a: 3
};
// foo()不是箭頭函數,他的this被綁定到obj1
var bar = foo.call( obj1 ); // foo.call( obj1 )返回箭頭函數,所以bar為箭頭函數
bar.call( obj2 ); // 2! 箭頭函數的this無法被修改,new也不行

如下為和箭頭函數一樣的模式:

function foo() {
  var self = this; // lexical capture of `this`
  setTimeout( function(){
    console.log( self.a );
  }, 100 );
}
var obj = {
  a: 2
};

更多關于JS中this對象的相關文章大家可以點擊下面的相關鏈接

相關文章

  • JavaScript 反射學習技巧

    JavaScript 反射學習技巧

    這篇文章主要給大家分享的是JavaScript 的反射學習技巧,主要是區(qū)別在于所有的函數對象屬性過于復雜,而且額外增加可能會導致程序行為不合理,所以擴展 Reflect 函數來專門對函數對象處理調用方法,構造對象,獲取或者設置屬性等相關操作。下面一起進入文章內容吧
    2021-10-10
  • JavaScript內置對象介紹

    JavaScript內置對象介紹

    這篇文章主要介紹了JavaScript內置對象,內置對象就是指?JS?語言自帶的一些對象,這些對象供開發(fā)者使用,并提供了一些常用的或是最基本而必要的功能,下面我們一起進入文章了解更多詳細內容
    2021-12-12
  • js 實現驗證碼輸入框示例詳解

    js 實現驗證碼輸入框示例詳解

    這篇文章主要為大家介紹了js 實現驗證碼輸入框示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • 微信小程序 Record API詳解及實例代碼

    微信小程序 Record API詳解及實例代碼

    這篇文章主要介紹了微信小程序 Record API詳解及實例代碼的相關資料,需要的朋友可以參考下
    2016-09-09
  • javascript使用btoa和atob來進行Base64轉碼和解碼

    javascript使用btoa和atob來進行Base64轉碼和解碼

    javascript原生的api本來就支持,Base64,但是由于之前的javascript局限性,導致Base64基本中看不中用。當前html5標準正式化之際,Base64將有較大的轉型空間,對于Html5 Api中出現的如FileReader Api, 拖拽上傳,甚至是Canvas,Video截圖都可以實現
    2017-03-03
  • 微信小程序 按鈕滑動的實現方法

    微信小程序 按鈕滑動的實現方法

    這篇文章主要介紹了微信小程序 按鈕滑動的實現方法的相關資料,希望通過本文能幫助到大家實現這樣的功能,需要的朋友可以參考下
    2017-09-09
  • 微信小程序 form組件詳解

    微信小程序 form組件詳解

    這篇文章主要介紹了微信小程序 form組件詳解的相關資料,需要的朋友可以參考下
    2016-10-10
  • await vs return vs return await關鍵區(qū)別解析

    await vs return vs return await關鍵區(qū)別

    這篇文章主要為大家介紹了await vs return vs return await關鍵區(qū)別解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • JS前端使用canvas搞一個手勢識別

    JS前端使用canvas搞一個手勢識別

    這篇文章主要為大家介紹了JS前端使用canvas搞一個手勢識別的實現示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • 微信小程序 共用變量值的實現

    微信小程序 共用變量值的實現

    這篇文章主要介紹了微信小程序 共用變量值的實現的相關資料,需要的朋友可以參考下
    2017-07-07

最新評論