国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

JavaScript中this的全面解析及常見實例

2019-11-19 11:34:54
字體:
來源:轉載
供稿:網友

前言

this 關鍵字在 Javascript 中非常常見,但是很多開發者很難說清它到底指向什么。大部分人會從字面意思上去理解 this,認為 this 指向函數自身,實際上this 是在運行時進行綁定的,并不是在編寫時綁定,它的上下文取決于函數調
用時的各種條件。this 的綁定和函數聲明的位置沒有任何關系,只取決于函數的調用方式。

總結: 函數被調用時發生 this 綁定,this 指向什么完全取決于函數在哪里被調用。

一、this 的綁定規則

this 一共有 4 中綁定規則,接下來一一介紹每種規則的解釋和規則直接的優先級

  • 默認綁定(嚴格/非嚴格模式)
  • 隱式綁定
  • 顯式綁定
  • new 綁定

1.1 默認綁定(嚴格/非嚴格模式)

  • 獨立函數調用: 獨立函數調用時 this 使用默認綁定規則,默認綁定規則下 this 指向 window(全局對象)。
  • 嚴格模式下: this 無法使用默認綁定,this 會綁定到 undefined。

獨立函數調用

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

嚴格模式下:

function foo() { "use strict"; console.log(this); //undefined console.log(this.a); //Uncaught TypeError: Cannot read property 'a' of undefined}var a = 2;foo();

注意下邊兩種情況

var age = "18";var obj = { name: "heyushuo", age: 25, fn: function() { function sayName() {  console.log(this); //window  console.log(this.age); //undefined } sayName(); }};obj.fn();

函數 sayName 雖然是在 obj.fn 內部定義的,但是它仍然是一個獨立函數調用,this 仍然指向 window。

var a = "global";var obj = { a: 2, foo: function() { console.log(this.a); //global }};var bar = obj.foo; // 函數別名!bar();

雖然 bar 是 obj.foo 的一個引用,但是實際上,它引用的是函數本身,因此此時的
bar() 其實是一個不帶任何修飾的獨立函數調用,因此應用了默認綁定。

1.2 隱式綁定

當函數引用有上下文對象時(例如:obj.foo 這個時候使用 obj 上下文來引用函數 foo),隱式綁定規則會把函數中的 this 綁定到這個上下文對象。

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

對象屬性引用鏈中只有上一層或者說最后一層在調用中起作用。

var obj = { name: "heyushuo", obj1: { name: "kebi", foo: function() {  console.log(this.name); // kebi } }};obj.obj1.foo();

隱式丟失

被隱式綁定的函數會丟失綁定對象,而應用默認綁定,把 this 綁定到全局對象或者 undefined(嚴格模式) 上。

第一種

var a = "global";var obj = { a: 2, foo: function() { console.log(this.a); //global }};var bar = obj.foo; // 函數別名!bar();

雖然 bar 是 obj.foo 的一個引用,但是實際上,它引用的是函數本身,因此此時的bar() 其實是一個不帶任何修飾的獨立函數調用,因此應用了默認綁定。

第二種傳入回調函數時:

var a = "global";var obj = { a: 2, foo: function() { console.log(this.a); //global }};var bar = obj.foo; // 函數別名!function doFoo(fn) { fn(); // <-- 調用位置!}doFoo(bar); //global//和下邊這種一樣setTimeout(obj.foo, 300);

1.3 顯示綁定

通過 call() 或者 apply()方法。第一個參數是一個對象,在調用函數時將這個對象綁定到 this 上,稱之為顯示綁定。

function foo() { console.log(this.a);}var obj = { a: 2};foo.call(obj); // 2

顯示綁定引申出來一個硬綁定,代碼如下

function foo(something) {  console.log( this.a, something );  return this.a + something;}// 簡單的輔助綁定函數function bind(fn, obj) {  return function() { return fn.apply( obj, arguments ); //內部已經強制綁定了傳入函數this的指向 };}var obj = {  a:2};var bar = bind( foo, obj ); var b = bar( 3 ); // 2 3console.log( b ); // 5

bar函數無論如何調用,它總會手動在 obj 上調用 fn,強制把 fn 的 this 綁定到了 obj。這樣也解決前面提到的丟失綁定問題
由于硬綁定是一種非常常用的模式,所以在 ES5 中提供了內置的方法 Function.prototype.bind

function foo(something) {  console.log( this.a, something );  return this.a + something;}var obj = {  a:2};var bar = foo.bind( obj );var b = bar( 3 ); // 2 3 console.log( b ); // 5

1.4 new綁定

使用new來調用函數,或者說發生構造函數調用時,會自動執行下面的操作。

  • 創建(或者說構造)一個全新的對象。
  • 這個新對象會被執行 [[ 原型 ]] 連接。
  • 這個新對象會綁定到函數調用的 this。
  • 如果函數沒有返回其他對象,那么 new 表達式中的函數調用會自動返回這個新對象。

例如:

function foo() {  this.name = "heyushuo"; this.age = 25} foo.prototype.sayName = function(){ console.log(this.name+this.age);}var bar = new foo();console.log(bar); //{name: "heyushuo", age: 25}//這個新對象會綁定到函數調用的 this。所以此時的this就是bar對象console.log( bar.age ); // 25

如下圖是 new foo() 這個對象

二、四種綁定關系的優先級

判斷this,可以按照下面的順序來進行判斷:

1、函數是否在 new 中調用(new 綁定)?如果是的話 this 綁定的是新創建的對象。

var bar = new foo()

2、函數是否通過 call、apply(顯式綁定)或者硬綁定調用?如果是的話,this 綁定的是指定的對象。

var bar = foo.call(obj2)

3、函數是否在某個上下文對象中調用(隱式綁定)?如果是的話,this 綁定的是那個上下文對象。

var bar = obj1.foo()

4、如果都不是的話,使用默認綁定。如果在嚴格模式下,就綁定到 undefined,否則綁定到全局對象。

var bar = foo()

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對武林網的支持。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 江津市| 浏阳市| 东莞市| 惠水县| 娱乐| 龙川县| 荆州市| 永州市| 什邡市| 综艺| 建水县| 台中县| 普陀区| 西充县| 蓬安县| 佛山市| 鹤壁市| 汶上县| 苏尼特左旗| 湟中县| 剑川县| 棋牌| 特克斯县| 沂源县| 会同县| 白山市| 宾川县| 比如县| 思南县| 旌德县| 叙永县| 通山县| 贵港市| 漳浦县| 台东县| 八宿县| 黄梅县| 临潭县| 墨脱县| 沅江市| 阜平县|