this, call, apply 和 bind

初衷:

这篇关于this的文章,仅仅是自己认为比较重要且易混淆的知识点。

内容

1.含义:

JavaScript中,this对象是指当前函数中正在执行的上下文环境,因此this并非是定义时(箭头函数除外)。

2.this指向:

永远指向最后调用它的对象。 简单记忆:A.B()这里的this就指.左边的A.

3.this对象分类:
  • this对象分类:
    • 全局对象
    • 当前对象
    • 任意对象

判断处于哪种this对象,这个取决于函数的调用方式。而JavaScript中的函数调用方式又分为四种:

  • JavaScript中的函数调用方式:
    • 函数调用
    • 作为对象的方法调用
    • 构造函数调用
    • call 、apply 、bind
4. 具体内容:
4.1 函数调用
var a = 11;
function foo() {
    var a = 22;
    console.log(this.a);//11
}
foo();
console.log(this.a);//11
复制代码
function foo() {
    console.log( a ); 
}

function bar() {
    var a = 3;
    foo();
}

var a = 2;

bar();//2
复制代码

函数调用:在独立调用中,this在非严格模式下指向全局对象window.在严格模式下thisundefined。在这里,用var声明一个变量和给this以及window添加属性是等价的。

var myname = "princess";
console.log(this.myname); //princess
console.log(window.myname); //princess
复制代码

接着可能会有下面的疑惑:

var foo = 123;//foo 是变量
window.bar = 345;//bar 是属性
delete foo;
delete bar;
console.log(this.foo,this.bar);//123,undefined  为什么不一样呢?
复制代码

delelte删除不了变量、删除不了原型链中的变量、可以删掉对象属性!

还得注意以下一点:

(…)();这样形式(IIFE(立即调用的函数表达式))封装的函数会立即被调用,也就是说等同于被独立调用,因此它内部的this全局变量,所以输出的是全局变量。

4.2 作为对象的方法调用
var b = 33;
var o = {
    b: 44,
    f: function() {
        return this.b;
    }
};
console.log(o.f());//44
复制代码

作为对象的方法调用this指向该对象(这里即对象o)。

但是当对象的方法被赋予给一个变量时,其相当于函数触发,此时的this为 window (非严格模式下)或者 undefined(严格模式下)。

var b = 33;
var o = {
    b: 44,
    f: function() {
        return this.b;
    }
};
console.log(o.f());//44
var c = o.f;    // this == window || undefined
c();//33
复制代码
4.3 构造函数调用
  • new 方法创建对象的时候,会经过如下过程:
    • 创建对象,将this值赋予新的对象;
    • 调用构造函数,为this添加属性和方法;
    • 返回this给当前的对象.

注意关键字 new

function Person(name, age) {
    this.name = name;
    this.age = age;
    return {
        name: 'Mary'
    };
}
var person1 = new Person('Jack');
console.log(person1.name);    // 'Mary'
console.log(person1.age);     // undefined
复制代码

而下面的情况:

function Person(name, age) {
    this.name = name;
    this.age = age;
    return this;
}

var person1 = Person('Bob', 18);
console.log(person1.name);    // Bob
console.log(window.name);     // Bob
console.log(person1 === window);    // true
复制代码

构造函数调用this指向该实例对象。

4.4 call 、apply 、bind

callapply均可以改变this指向,差别在于传入参数的不同。

A.call(this,arg1,arg2...,argn)

A.apply(this,[arg1,arg2...,argn])

如果第一个参数为null或者undefined,那么就非严格模式下默认为此时的thiswindow对象,严格模式下为undefined.而bind函数返回的是一个新的函数,即方法,不是立即执行函数,需要手动去调用bind().

使用 bind()方法创建的上下文,其为永久的上下文环境,不可修改,即使是使用 call 或者 apply方法,也无法修改 this 所指向的值。

5. 还有一种情况:

箭头函数:此时会从包裹它的函数或作用域中获取this的值。

箭头函数中的this定义它的时候已经决定了,与如何调用以及在哪里调用它无关,包括 (call, apply, bind)等操作都无法改变它的this

var x=11;
var obj={
 x:22,
 y:this,
 say:()=>{
   console.log(this.x);
 }
}
obj.say();//11
console.log(obj.y);//window
复制代码

这里按照上述“定义”时决定this指向,应该输出22,但是又可以看出obj对象中的this指代的是window,也就是全局环境,故箭头函数中的this就会就近找到上一个对象中this所指代的对象。obj内部属性y就为obj内部this指代的对象,输出是window.

关于这点,解释的还不是太清楚,再补充!

结语

温故而知新。

转载于:https://juejin.im/post/5cd4eb69f265da03761ea631

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值