美文网首页
深入之从this

深入之从this

作者: 明里人 | 来源:发表于2019-07-13 17:31 被阅读0次

当JavaScript代码执行一段可执行代码时,会创建对应的执行上下文。
对于每个执行上下文,都有三个重要属性

  • 变量对象
  • 作用域链
  • this
this 是什么

this既不指向函数自身,也不指向函数的词法作用域。它实际是在函数被调用时才发生的绑定,this具体指向什么,取决于你是怎样调用的函数。

this 的四种绑定规则
  • 默认绑定
  • 隐式绑定
  • 显示绑定
  • new 绑定
  • 箭头函数
默认绑定
function foo(){
  console.log(this.a);
}
var a = 2;
foo(); 

打印结果为2.
因为foo()是直接在全局调用的,进行了默认绑定,this指向了window。

注意:在严格模式下,全局对象将无法使用默认绑定,执行会保undefined错误

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

有时候,函数的调用是在某个对象上触发的

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

obj.foo 打印结果是3,foo通过obj调用,此时this指向obj对象,访问obj的属性a。如果obj没有属性a,也不会向上访问全局的a,此时打印为undefined。

多层调用链
function foo(){
    console.log(this.a);
}
var a = 2;
var obj1 = {
    a: 4,
    foo: foo
};
var obj2 = {
    a: 3,
    obj1: obj1
};
obj2.obj1.foo();

obj2.obj1.foo 打印结果为4。
这里调用链不只一层,存在obj1、obj2两个对象,但foo中的this会指向最近一次的调用者 ---- obj1。

隐式丢失(函数别名)
function foo(){
    console.log(this.a);
}
var a = 2;
var obj = {
    a: 3,
    foo: foo
};
var bar = obj.foo;
bar();

打印结果是2。尽管obj隐式绑定了foo,但将其赋值给bar,而bar在全局调用,所以访问全局的a。

显式绑定

通过call() 、apply()、bind()来实现。

function foo(){
    console.log(this.a);
}
var a = 2;
var obj1 = {
    a: 3
}
var obj2 = {
    a: 4
}
foo.call(obj1);
foo.apply(obj2);
foo.bind(obj1)();

打印结果是3,4。
因为这里显式的申明了要绑定的对象,所以this就被绑定到了obj1和obj2

new 绑定

如果函数没有返回其他对象,那么函数中的this指向new 返回的这个对象。

function Foo(a){
  this.a = a;
}
var a = 2;
var bar1 = new Foo(3);
console.log(bar1.a);  // 3
var bar2 = new Foo(4);
console.log(bar2.a);  // 4
箭头函数

箭头函数本身不存在this,this指向上一级对象
看一个例子

function Person(){
    this.age = 0;
    setTimeout(function(){
        this.age ++;
        console.log(this,this.age);  // this指向window
    },1000)
}
let person = new Person();

如果我们想在计时器中访问Person的成员属性,通常会这样做

function Person(){
    this.age = 0;
    let self = this;
    setTimeout(function(){
        self.age ++;
        console.log(self,self.age);  // this指向Person
    },1000)
}
let person = new Person();

使用箭头函数可以达到这样效果,将this指向上一级对象

function Person(){
    this.age = 0;
    setTimeout(() => {
        this.age ++;
        console.log(this,this.age);  // this指向Person
    },1000)
}
let person = new Person();

相关文章

网友评论

      本文标题:深入之从this

      本文链接:https://www.haomeiwen.com/subject/bccmkctx.html