javascript绑定this的几种方法

版权声明:欢迎转载,转载请注明原始出处 https://blog.csdn.net/xiaomingelv/article/details/84260611

首先 ,理清一下js中的this,js中的this对象指向调用当前方法的对象,这个指向是在执行的时候才确定下来的,跟函数在何时何处声明是无关的。

但是,在实际使用过程中,我们经常会遇到要改变当前this指向的需求,一下的对绑定this方法的归纳

1、call和apply

这里把call和apply放在一起讲,是因为这两个方法及其相似,其作用都是直接调用一个函数,并使其具有一个指定的this,区别在于,就是call()方法接受的是若干个参数的列表,而apply()方法接受的是一个包含多个参数的数组。具体使用方法如下

function Product(name, price) {
  this.name = name;
  this.price = price;
}

function ProductExtra(from,to){
   this.from=from;
   this.to=to;
}

function Food(name, price,extra) {
  Product.call(this, name, price);
  ProductExtra.apply(this,extra);
  this.category = 'food';
}

console.log(new Food('烤鸭', 5,['北京','广东']).name);//输出: "烤鸭"
console.log(new Food('烤鸭', 5,['北京','广东']).from);//输出: "北京"

通过对比我们可以看出,call函数第一个参数为要绑定的this,之后可以跟上无数个参数,这些参数会依次作为执行函数的参数传入,而apply则传入一个数组,这个数组中的内容则会按顺序作为执行函数的参数传入。

2、bind

bind函数时es5定义的一个函数,定义如下:func.bind(thisArg, arg1, arg2, ...),它与call和apply不同的是,bind不会直接执行要执行的函数,而是返回一个新的函数,我们称之为a,当执行a被调用执行时,arg1, arg2, ...这些参数,将置于实参之前传递给a,示例代码如下

function product(name, price) {
  console.log(name);
  console.log(price);
  console.log(this.from);
  console.log(this.to);
}

function test(price){
var extra={from:'北京',to:'广东'};
var productWithExtra =product.bind(extra,'烤鸭');
productWithExtra(price);
}

test(50);//输出:"烤鸭",50,"北京","广东"

有一点必须注意的是,对任何函数进行bind绑定之后返回的函数,如果再次进行bind绑定是不会有效果的,bind函数绑定后返回的函数,再次进行绑定依旧会指向第一次绑定的对象,具体原因可以了解bind函数的实现原理 

3箭头函数

箭头函数是es6定义的一个写法,写法类似于()=>{console.log(test);}可以看做是匿名函数的另外一种写法,这里不对箭头函数的特性做详细的解读,仅对其绑定this方面做部分解析,箭头函数中的this跟正常的this不太一样,正常函数的this是在执行时确定下来的,指向调用当前方法的对象,而箭头函数则不同,箭头函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象,也就是所谓的词法作用域,在定义的时候就确定下来了,例如

var obj1 = {
    birth: 1990,
    getBirth: function () {
        var b = this.birth; // 1990
        var fn = function () {
            return this.birth; // this指向window或undefined,this.birth的值不确定
        };
        return fn();
    }
};

var obj2 = {
    birth: 1990,
    getBirth: function () {
        var b = this.birth; // 1990
        var fn = () => this.birth; // this指向obj对象,this.birth=1990
        return fn();
    }
};

console.log(obj1.getBirth())//无法获得预期效果
console.log(obj2.getBirth())//输出1990

正因为箭头函数的这个特性,我们可以利用它来改变当前函数的this指向

4双冒号::

双冒号属于es尚未通过的一个提案,但目前babel已经支持,可以把它理解为一个语法糖,可以用它来代替bind,具体使用方法如下

obj::func;
// 等同于
func.bind(obj);


obj::obj.func;
// 等同于
::obj.func;

使用方法其实很简单,双冒号后面是要执行的函数,双冒号前面是要绑定的对象,如果双冒号左边为空,右边是一个对象的方法,则等于将该方法绑定在该对象上面,它跟bind一样,执行之后返回一个新的函数,而不是立即执行这个函数

参考资料:

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/call

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/apply

http://es6.ruanyifeng.com/?search=%3A%3A&x=3&y=10#docs/function#%E5%8F%8C%E5%86%92%E5%8F%B7%E8%BF%90%E7%AE%97%E7%AC%A6

猜你喜欢

转载自blog.csdn.net/xiaomingelv/article/details/84260611