龙空技术网

一句话解释 JavaScript 的 this

是蜃楼啊 347

前言:

目前朋友们对“jsthishtml”都比较关怀,姐妹们都需要了解一些“jsthishtml”的相关文章。那么小编也在网络上收集了一些对于“jsthishtml””的相关知识,希望兄弟们能喜欢,大家快快来了解一下吧!

一句话解释 this

如何一句话解释 this:它就是一个变量,指向了某个对象保存在堆中的数据。

从原理角度理解 this

我们知道在 JS 中,对象的变量名保存在栈(Stack)中,对象的数据保存在堆(Heap)中,像这样:

一句话解释 this,它就是一个变量,引用了某个对象保存在堆中的数据,就这么简单。 比如在上图中,personAthis 引用了 {name: "LB", age:20}

this 有什么用?

既然 this 指向的堆中某个对象的数据,那我们可以通过 this 来灵活的操作对象在堆中的数据呀。

比如下面的代码,可以把一个sayHi函数放在两个对象身上使用,代码可复用性这不就上来了么:

const user = { name: "john" };const admin = { name: "admin" };function sayHi() {  console.log(this.name); // this 可以指向 user,也可以指向 admin}user.f = sayHi;admin.f = sayHi;user.f();  // johnadmin.f();  // admin
把 this 掌握在自己手里

只有掌握好 this 的指向规则,才能让我们使用 this 的时候可以指哪打哪。

如何操纵普通函数的 this ?

普通函数的 this 的指向可以通过下面几种规则来判断,优先级从高到低:

看是不是 new 调用。函数是否在 new 中调用? 如果是的话 ,this 绑定的是新创建的对象。

var bar = new foo()
看是不是显示绑定。函数是否通过 call、apply、bind 调用? 如果是的话,this 绑定的是 指定的对象。
 var bar = foo.call(obj2)
看是不是隐式绑定。函数是否在某个上下文对象中调用? 如果是的话,this 绑定的是那个上下文对象。
var bar = obj1.foo()
如果都不是的话,使用默认绑定。如果在严格模式下,就绑定到 undefined,否则绑定到 全局对象。
 var bar = foo()

普通函数的 this 绑定是动态的,也就是在运行时才知道 this 绑定的是谁的 context,再具体一点来说,this 所在的函数被谁调用了,this 就绑定了谁的上下文。如果这个谁也没有上下文,就再往上看上一层调用者,直到找到有上下文的函数 (最顶层就是拥有全局上下文的全局函数)。

从调用栈的角度来说,一个普通函数出栈后,就有一个新的栈顶函数,然后被调用,这个函数的 this 绑定的是新的栈顶函数的上下文。

如何操纵箭头函数的 this ?

箭头函数可以理解为轻量级的普通函数,它压根就没有 this,所以普通函数的 this 规则不适用于它。它的 this 在创建函数的时候,从外层的 this 继承而来,而且一旦继承了 this,就不会再变了。

在创建箭头函数的时候,this 继承自外部,而且 this 确定之后不会变:

function foo() {  return (a) => {    // this 继承自 foo()    // this 继承之后不会变    console.log(this.a);  };}var obj1 = { a: 2 };var obj2 = { a: 3 };var bar = foo.call(obj1); // 调用 foo,foo 的 this 指向 obj1bar.call(obj2); // 2

因为不用担心 this 的指向会被三方库修改,所以常用在创建回调函数:

function foo() {  setTimeout(() => {    // 这里的 this 继承自 foo,不用担心 setTimeout 会修改它    console.log(this.a);  }, 100);}var obj = { a: 2 };foo.call(obj); // 2

下面的代码和上面的一样,把回调函数的声明抽出来了,更好理解:

function foo() {  const cb = () => {    // 这里的 this 继承自 foo    console.log(this.a);  };  setTimeout(cb, 100);}var obj = { a: 2 };foo.call(obj); // 2
代码实操

下面的例子,如果没有额外说明 use strict,都是没有 use strict 的。 推荐你配合着上面的 this 绑定规则一起看下面的代码。

默认绑定:

function makeUser() {  return {    name: "John",    ref: this  };}// this 的指向只和 function 在哪里 call 有关系let user = makeUser();console.log( user.ref.name ); // Error: Cannot read property 'name' of undefinedoo

隐式绑定:

"use strict";function makeUser() {  return {    name: "John",    ref() {      return this;  // 拿的是 makeUser 的 this    },  };}let user = makeUser();// user 是一个对象,user.ref() 相当于隐式绑定了 thisconsole.log(user.ref().name); // John

箭头函数的 this 继承自外层:

obj = {  count: 0,  cool: function coolFn() {    if (this.count < 1) {      setTimeout(() => {   // 箭头函数的 this 就是 coolFn() 的 this        console.log("awesome");      }, 100);    }  },};obj.cool(); // awesome// 下面代码是一样的obj = {  count: 0,  cool: function coolFn() {    if (this.count < 1) {      let foo = () => {	    // 箭头函数的 this 就是 coolFn() 的 this        console.log("awesome");      };      setTimeout(foo, 100);    }  },};obj.cool(); // awesome

标签: #jsthishtml #是js #jsthis理解 #html一句话