likes
comments
collection
share

还在猜this指向谁吗?快来看看this的指向规则~

作者站长头像
站长
· 阅读数 27

前言

为什么要有this?

为了让对象中的函数有能力访问对象自己的属性

this的好处?

this可以显著的提升代码质量,减少上下文参数的传递

正文

this的绑定规则

默认绑定

定义

当一个函数独立调用,不带任何修饰符的时候为默认绑定。

代码分析(该代码拿到页面的控制台运行,因为node没有window)

代码一

function foo() {
    console.log(this); // window
}

foo(); 

还在猜this指向谁吗?快来看看this的指向规则~

代码二

function foo() {
    console.log(this); 
}

function bar() {
    foo();
}
function baz() {
    bar();
}

baz();

还在猜this指向谁吗?快来看看this的指向规则~

分析

该函数为独立调用,因此为默认绑定,这个时候就要看这个函数在哪个词法作用域下生效,foo在全局作用域下生效,因此this指向的window。

this指向分析

函数在哪个词法作用域下生效,函数中的this就指向哪(简述就是只要是默认绑定,this一定指向window)。

隐式绑定

定义

当函数的引用上下文对象的时(当函数被某个对象所拥有时)为隐式绑定。

代码一

var obj = {
    a: 1,
    b: this,
    foo: function() {
      console.log(this); // obj
    }
}

obj.foo();

还在猜this指向谁吗?快来看看this的指向规则~

分析

该函数的引用有上下文对象,因此为隐式绑定,隐式绑定的规则是this指向引用它的对象。

代码二

var obj = {
    a: 1,
    b:  function() {
      foo();
    }
}

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

还在猜this指向谁吗?快来看看this的指向规则~

分析

obj.b()相当于调用函数foo(),所以此时为默认绑定,this指向全局,那么这个时候就会去全局查找属性a,所以输出的为2。

this指向

函数的this指向引用它的对象。

隐式丢失

定义

当一个函数被多个对象链式调用时,函数的this指向就近的那个对象。

代码一

var obj = {
    a: 1,
    foo: foo
}

var obj2 = {
    a:2,
    obj: obj
}
function foo() {
    console.log(this.a)
}

obj2.obj.foo();

还在猜this指向谁吗?快来看看this的指向规则~

分析

函数被多个对象链式调用时,函数的this指向就近的那个对象,此时this指向obj,所以输出的为1.

代码二

var obj = {
    a: 1,
    foo: foo()
}

function foo() {
    console.log(this.a)
}

obj.foo;

还在猜this指向谁吗?快来看看this的指向规则~

分析

obj.foo就相当于foo(),所以此时为默认绑定,this指向全局,所以输出undefined。

显式绑定

call

代码

var obj = {
    a: 1
}

function foo(x, y) {
    console.log(this.a, x + y);
}

foo.call(obj, 2, 3);

还在猜this指向谁吗?快来看看this的指向规则~

分析

call可以让foo里的this绑定到obj,并且call还可以传递其他的参数给foo。

apply

代码

var obj = {
    a: 1
}

function foo(x, y) {
    console.log(this.a, x + y);
}

foo.apply(obj, [2, 3]);

还在猜this指向谁吗?快来看看this的指向规则~

分析

apply和call差不多,但是有一个区别就是,apply传递其他的参数给foo时是使用数组的形式进行传递的。

bind

代码

var obj = {
    a: 1
}

function foo(x, y) {
    console.log(this.a, x + y);
}

bind会返回一个函数,定义一个bar接收该函数,然后调用

方法一(通过bind传参,和call一样的形式)

var bar = foo.bind(obj, 2, 3);
bar();

方法二(bind和bar结合传参)

var bar = foo.bind(obj);
bar(2, 3);

方法三(bind和bar结合传参)

var bar = foo.bind(obj, 2);
bar(3);

方法四(bind和bar结合传参,多出的参数,根据就近原则,优先bind)

var bar = foo.bind(obj, 2, 3);
bar(4);

还在猜this指向谁吗?快来看看this的指向规则~

new 绑定

function Person() {
    this.name= '李总'
}

let p = new Person(); //this指向实例对象
let p2 = new Person(); 

this指向

this指向创建的实例对象

箭头函数

箭头函数没有this这个机制,写在箭头函数中的this也是它外层非箭头函数的this

代码一

function foo() {
var bar = () => {
   console.log(this);
}
//箭头函数没有this,即bar没有this,不能说bar的this,只能说bar里的this
bar();
}

foo();

还在猜this指向谁吗?快来看看this的指向规则~

分析

箭头函数没有this这个机制,所以看他的外层非箭头函数bar,bar为默认绑定,所以this指向window。

代码二

var obj = {
    a: 1,
    b: function () {
       const fn = () => {
       console.log(this.a);
       console.log(this);
       }
       fn();
    }
}

obj.b();

还在猜this指向谁吗?快来看看this的指向规则~

分析

箭头函数没有this这个机制,看外层函数fn,绑定为隐式绑定,this指向obj,所以输出1。

结语

看完有没有对this指向清晰点呢?记得和我分享分享哦~

还在猜this指向谁吗?快来看看this的指向规则~

转载自:https://juejin.cn/post/7366426339278798884
评论
请登录