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

深入了解JavaScript中的this關(guān)鍵字指向

 更新時(shí)間:2023年07月24日 10:57:23   作者:coder_7  
這篇文章主要介紹了深入了解JavaScript中的this關(guān)鍵字指向,在大多情況下,this出現(xiàn)在函數(shù)中,this指向什么,跟函數(shù)定義的位置無關(guān),跟函數(shù)調(diào)用方式有關(guān),需要的朋友可以參考下

全局作用域的this

  • 游覽器:非嚴(yán)格模式指向window,嚴(yán)格模式指向undefined
  • Node環(huán)境:指向{}
    • 把文件看作module -> 加載編譯 -> 放到一個(gè)函數(shù)中 -> 通過 apply({})/call({}) 執(zhí)行這個(gè)函數(shù)

調(diào)用方式不同,this指向不同

在大多情況下,this出現(xiàn)在函數(shù)中。this指向什么,跟函數(shù)定義的位置無關(guān),跟函數(shù)調(diào)用方式有關(guān)(綁定規(guī)則相關(guān))

function foo(){
	console.log(this);
}
var obj = {
	foo: foo
}
//不同的調(diào)用方式this的指向不同,不同的調(diào)用方式對(duì)應(yīng)著不同的綁定規(guī)則
foo();//window
obj.foo();//obj
foo.call("123");//String{"abc"}

this的綁定規(guī)則

  1. 默認(rèn)綁定:函數(shù)獨(dú)立調(diào)用方式,this指向全局對(duì)象
  2. 隱式綁定:通過對(duì)象調(diào)用方法,會(huì)隱式的將this指向當(dāng)前對(duì)象
  3. 顯示綁定:通過函數(shù)的apply、call、bind方法改變函數(shù)中this的指向
    • apply/call:會(huì)自動(dòng)調(diào)用,第一個(gè)參數(shù)都是設(shè)置this的指向,apply第二個(gè)參數(shù)為數(shù)組,call后面?zhèn)魅霝閰?shù)列表。
    • bind:不會(huì)自動(dòng)調(diào)用,會(huì)返回一個(gè)已經(jīng)綁定好this的函數(shù),傳參與call一樣
  4. new綁定 :通過new關(guān)鍵字調(diào)用函數(shù),new 函數(shù)()
    • 創(chuàng)建一個(gè)全新的對(duì)象
    • 這個(gè)新對(duì)象會(huì)被執(zhí)行prototype連接
    • 執(zhí)行構(gòu)造函數(shù)中的代碼,為新對(duì)象添加屬性(this綁定在這個(gè)步驟完成)
    • 如果函數(shù)沒有返回其他對(duì)象,表達(dá)式會(huì)返回這個(gè)新對(duì)象

this綁定優(yōu)先級(jí)(權(quán)重)

  • 示綁定(bind>call/apply) > 隱式綁定 > 默認(rèn)綁定
function fn() {
  console.log(this);
}
fn.bind(123).apply(321);
  • new 綁定 > 隱式綁定 > 默認(rèn)綁定
  • new 綁定 > 顯示綁定(通過bind綁定this的函數(shù),可以被new關(guān)鍵字改變this指向)
function Fn(){
  console.log(this);
}
fn.bind("132");
var obj = new Fn();
  • new關(guān)鍵字不能和call/apply一起使用,因?yàn)閚ew會(huì)主動(dòng)調(diào)用函數(shù),call/apply也會(huì)主動(dòng)調(diào)用函數(shù),這樣會(huì)產(chǎn)生沖突報(bào)錯(cuò)

綁定優(yōu)先級(jí):new 綁定 > 顯示綁定 > 隱式綁定 > 默認(rèn)綁定

this規(guī)則之外

忽略顯示綁定

apply/call/bind:當(dāng)傳入null/undefined時(shí),自動(dòng)將this綁定成全局對(duì)象

function fn(){
  console.log(this);
}
fn.apply(null);
fn.apply(undefined);

間接函數(shù)引用

var obj1 = {
	foo: function(){
		console.log(this);
	}
}
var obj2 = {}
;(obj2.bar = obj1.foo)()//括號(hào)中包含賦值表達(dá)式,屬于獨(dú)立函數(shù)調(diào)用,是默認(rèn)綁定,指向window

箭頭函數(shù) 將頭函數(shù)不會(huì)綁定this,arguments屬性箭頭函數(shù)不能作為構(gòu)造函數(shù)來使用(不能new對(duì)象) 簡(jiǎn)寫

  • 簡(jiǎn)寫一:當(dāng)參數(shù)只有一個(gè),可以省略括號(hào)
  • 簡(jiǎn)寫二:當(dāng)函數(shù)體只有一行,可以省略大括號(hào),并且會(huì)將這一行代碼的返回值return
var nums = [0, 1, 2, 3, 4, 5];
var result = nums
  .filter(item => item % 2 === 0)
  .map(item => item * 10)
  .reduce((preVal, curVal) => preVal + curVal, 0);
console.log(result);
  • 簡(jiǎn)寫三:如果只有一個(gè)行,且需要返回一個(gè)對(duì)象,那么要將對(duì)象用括號(hào)包裹。因?yàn)槭÷?quot;{}“后,不知道將對(duì)象的”{}"如何解析
var foo = () => ({ name: "foo", age: 18 });//這樣解析時(shí)會(huì)將對(duì)象當(dāng)作一個(gè)整體

箭頭函數(shù)的this綁定

箭頭函數(shù)不遵循this的四種標(biāo)準(zhǔn)規(guī)則,箭頭函數(shù)內(nèi)部沒有綁定this,也不能通過call/apply/bind綁定this,箭頭函數(shù)的this指向根據(jù)外層作用域決定

var obj = {
  getData() {
    setTimeout(function () {
      console.log(this);
    }, 200);
  },
};
//setTimeout中的函數(shù)屬于獨(dú)立調(diào)用,所以指向的是window
//如果想讓this指向obj對(duì)象,setTimeout中使用箭頭函數(shù)
obj.getData();

this相關(guān)面試題

面試題一:

var name = "window";
var person = {
  name: "person",
  sayName: function () {
    console.log(this.name);
  }
};
function sayName() {
  var sss = person.sayName;
  sss(); 
  person.sayName(); 
  (person.sayName)(); 
  (b = person.sayName)(); //包含賦值表達(dá)式,屬于間接函數(shù)引用
}
sayName();

答案:window(默認(rèn)綁定)、person(隱式綁定)、person(隱式綁定)、window(間接函數(shù)引用)

面試題二:

var name = 'window'
var person1 = {
  name: 'person1',
  foo1: function () {
    console.log(this.name)
  },
  foo2: () => console.log(this.name),
  foo3: function () {
    return function () {
      console.log(this.name)
    }
  },
  foo4: function () {
    return () => {
      console.log(this.name)
    }
  }
}
var person2 = { name: 'person2' }
person1.foo1(); 
person1.foo1.call(person2); 
person1.foo2();
person1.foo2.call(person2);
person1.foo3()();
person1.foo3.call(person2)();
person1.foo3().call(person2);
person1.foo4()();
person1.foo4.call(person2)();
person1.foo4().call(person2);

答案解析:

person1.foo1(); //person1:隱式綁定
person1.foo1.call(person2); //person2:顯示綁定
person1.foo2();//window:箭頭函數(shù)的this指向上層作用域的this
person1.foo2.call(person2);//window:箭頭函數(shù)的this指向上層作用域的this,且不能改變箭頭函數(shù)指向
person1.foo3()();//window:先執(zhí)行person1.foo3(),然后拿到返回的函數(shù)再調(diào)用,屬于獨(dú)立調(diào)用,所以指向window
person1.foo3.call(person2)();//window:先執(zhí)行person1.foo3.call(person2),拿到返回的函數(shù)再調(diào)用,屬于獨(dú)立調(diào)用
person1.foo3().call(person2);//person2:先執(zhí)行person1.foo3(),拿到返回的函數(shù)通過call調(diào)用this指向了person2
person1.foo4()(); //person1:拿到返回的箭頭函數(shù)后,箭頭函數(shù)沒有this,根據(jù)上層作用域決定,上層foo4函數(shù)指向的是person1對(duì)象(foo4是被person1直接調(diào)用的),所以內(nèi)部箭頭函數(shù)也指向peroson1
person1.foo4.call(person2)(); //person2:給foo4綁定this為person2,箭頭函數(shù)調(diào)用this指向上層作用域,上層foo4的this被顯示綁定為了person2,那么內(nèi)部的箭頭函數(shù)也是指向person2
person1.foo4().call(person2); //person1:call調(diào)用箭頭函數(shù),依然去上一層找,所以依然是person1

面試題三:

var name = 'window'
function Person (name) {
  this.name = name
  this.foo1 = function () {
    console.log(this.name)
  },
  this.foo2 = () => console.log(this.name),
  this.foo3 = function () {
    return function () {
      console.log(this.name)
    }
  },
  this.foo4 = function () {
    return () => {
      console.log(this.name)
    }
  }
}
var person1 = new Person('person1')
var person2 = new Person('person2')
person1.foo1()
person1.foo1.call(person2)
person1.foo2()
person1.foo2.call(person2)
person1.foo3()()
person1.foo3.call(person2)()
person1.foo3().call(person2)
person1.foo4()()
person1.foo4.call(person2)()
person1.foo4().call(person2)

答案與解析:

person1.foo1() //person1
person1.foo1.call(person2) //person2
person1.foo2() //person1:箭頭函數(shù),指向上層作用域的this,上層作用域是“Person構(gòu)造函數(shù)”
person1.foo2.call(person2) //person1::箭頭函數(shù),指向上層作用域的this,不能被顯示綁定
person1.foo3()() //window:拿到返回的函數(shù)后調(diào)用,屬于獨(dú)立調(diào)用
person1.foo3.call(person2)() //window:拿到返回的函數(shù)后調(diào)用,屬于獨(dú)立調(diào)用
person1.foo3().call(person2) //person2:通過call顯示綁定
person1.foo4()() //person1:返回的箭頭函數(shù)去上層作用域找,上層foo的this指向person1
person1.foo4.call(person2)()//person2:返回的箭頭函數(shù)去上層作用域找,上層this通過call指向了person2
person1.foo4().call(person2)//person1:箭頭函數(shù)的this不能被顯示綁定

面試題四:

var name = 'window'
function Person (name) {
  this.name = name
  this.obj = {
    name: 'obj',
    foo1: function () {
      return function () {
        console.log(this.name)
      }
    },
    foo2: function () {
      return () => {
        console.log(this.name)
      }
    }
  }
}
var person1 = new Person('person1')
var person2 = new Person('person2')
person1.obj.foo1()()
person1.obj.foo1.call(person2)()
person1.obj.foo1().call(person2)
person1.obj.foo2()()
person1.obj.foo2.call(person2)()
person1.obj.foo2().call(person2)

答案與解析:

person1.obj.foo1()() //window:獨(dú)立調(diào)用
person1.obj.foo1.call(person2)() //window:獨(dú)立調(diào)用
person1.obj.foo1().call(person2) //person2:call顯示綁定
person1.obj.foo2()() //obj:返回的是箭頭函數(shù),this由上層作用域foo2函數(shù)決定,foo2的this指向obj(foo2是被obj直接調(diào)用的),所以返回的箭頭函數(shù)this也是指向obj
person1.obj.foo2.call(person2)()//person2:箭頭函數(shù)上層作用域this被call指向person2,所以箭頭函數(shù)也是指向person2
person1.obj.foo2().call(person2)//obj:箭頭函數(shù)this不能被顯示綁定

到此這篇關(guān)于深入了解JavaScript中的this關(guān)鍵字指向的文章就介紹到這了,更多相關(guān)JavaScript中的this內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論