详解JavaScript中的this

由于JavaScript的this不同于C++、JAVA等语言,在开发中容易造成一些困扰,故总结一下Javascript中的this知识,以免踩坑。
个人博客原文链接:点此前往


this指向问题

一般情况

this的指向不是由函数定义在哪个对象里面决定的,而是函数执行时由谁”唤醒”或者说调用来决定的,即调用时才对this做绑定,而不是定义时。

箭头函数

如果用babel解析后可以发现,箭头函数本身并没有this,而是按照词法作用域来绑定上下文。所以箭头函数的this实际上指向的是原来的上下文(向上找一层)。
并且不同于一般的this绑定,箭头函数的this指向是在定义时确定(绑定上下文)的,并且一旦确定就不会被改变。

立即执行函数

立即执行函数的this指向window。但在严格模式下,其this指向undefined

example

例子来源: 《你不知道的JavaScript(上卷)》

var name = "Jay Global";
var person = {
    name: 'Jay Person',
    details: {
        name: 'Jay Details',
        print: function() {
            return this.name;
        }
    },
    print: function() {
        return this.name;
    }
};

/**
 * result: Jay Details
 * reason: 这里的print是由person.details调用的,所以this的指向为details
 * */
console.log(person.details.print());

/**
 * result: Jay Person
 * reason: 这里的print是由person调用的,所以this的指向为person
 * */
console.log(person.print());


var name1 = person.print;
var name2 = person.details;

/**
 * result: Jay Global
 * reason: 这里的name1实际上就是一个function,无调用对象。
 *         也可以看作是window调用的,所以this指向window。
 * */
name1();

/**
 * result: Jay Detail
 * reason: 这里的name2是一个Object,所以是name2调用了自身的一个函数。
 *         该函数的this指向name2这个对象。
 * */
name2.print();

修改this的指向

修改this的指向,主要有以下三方法: call、apply、bind

bind

语法:func.bind(this, [arg1, arg2...])

bind方法由函数调用,接收一个对象参数以及其他参数(可选)。bind会将func的this指向绑定的第一个参数上,后续传入的参数会绑定到func里作为传入参数。最后返回一个this经过改变的func。

应用场景:1、函数柯里化 2、函数借用(如下例)

let a = function () {
    let show = 1;
    console.log(this.show) 
}
let b = {
    show: 2
}
let c = a.bind(b);

c(); // 2

PS: bind的兼容性不好,ES3不支持,但我们可以手动创建一个bind:

// bind函数ES3实现
if (!Function.prototype.bind) {
    Function.prototype.bind = function(o/*,args*/){
        // 将this和arguments的值保存至变量中,以便在后面的嵌套函数中调用
        var self = this;
        var boundArgs = arguments;

        // bind()返回一个函数
        return function() {
            // 创建一个实参列表,将传入bind()的第二个及后续的实参都传入这个函数
            var args = [], i;
            for(i = 1; i < boundArgs.length; i++) args.push(boundArgs[i]);
            for(i = 0; i < arguments.length; i++) args.push(arguments[i]);

            return self.apply(o, args);
        }
    }
}

call & apply

语法:func.call(this, [arg1, arg2...])apply.bind(this, [Array])

1、call和apply用法与bind大致相同,不同之处在于call和apply使用后会立即执行更改this指向后的函数,而不是像bind那样返回
2、call和apply的区别在于:call除了第一个参数以外,可以像bind那样接收多个参数进行绑定。而apply则是接收一个数组。

apply由于可以接收数组,更适合用于数目可变的参数绑定。
但是由于多了一步解析数组参数的过程,会比call处理速度稍稍慢些,因此在参数少且不变的情况下建议用call。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值