02 this、call和apply

139 阅读2分钟

读书笔记:JS设计模式与开发实践

1 this

JS的this着是指向一个对象,而具体指向哪个对象是运行时基于函数的执行环境动态绑定的,而非函数被声明时的环境。

1-A this指向

  • 作为对象的方法调用
  • 作为普通函数调用
  • 构造器调用
  • Function.prototype.call 或 Function.prototype.call调用

1-A-a 作为对象的方法调用时,this指向该对象

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

1-A-b 作为普通函数(不作为对象的属性)被调用时,this指向全局对象。在浏览器里即window,在node里即global

window.name = 'globalName';
var getName = function(){
  return this.name;
}
console.log(getName());

有时我们会遇到一些困扰,比如div节点是事件函数,callback内部的this指向了window,但我们想让它指向该div节点

可在外部保存_this指向,es6解决方式为箭头函数

1-A-c 构造器调用时,this指向new的对象

var MyClass = function(){
  this.name = 'sven'
}
var obj = new MyClass()
console.log(obj.name);  //sven

1-A-d Function.prototype.call 或 Function.prototype.call可动态改变传入函数this

var obj1 = {
  name: 'sven',
  getName: function(){
    return this.name;
  }
}

var obj2 = {
  name: 'anne'
}

console.log(obj1.getName());              // sven
console.log(obj1.getName.call(obj2));     // anne

1-B 丢失的this

var obj = {
  myName: 'sven',
  getName: function(){
    return this.myName;
  }
}

console.log(obj.getName());  // sven

var getName2 = obj.getName;  // undefined
console.log(getName2());

调用getName2 返回undefined是因为:当用变量getName2来引用obj.getName,并且调用时。此时是普通函数调用方式,this指向全局。

2 call 和 apply

能熟练运用这两个方法,是JS程序员进阶重要一步。

2-A call和 apply的区别

apply接受两个参数,第一个参数指定了函数体内this对象的指向,第二个参数为一个带下杆的集合,可是数组或类数组。

var func = function(a, b, c){
  console.log([a,b,c]);
}

func.apply(null, [1,2,3])

call 传入的参数数量不固定,第一个参数为this指向,第二个开始,每个参数都被依次传入函数

var func = function (a, b, c) {
  console.log([a, b, c]);

}
func.call(null, 1, 2, 3)

当使用call或apply时,如第一个参传入null,函数体内的this会指向默认的宿主对象,浏览器中就是window。但在严格模式下,函数体内的this还是为null

有时我们使用call或apply的目的不在于指定this指向,而是另有用途,如借用其他对象的方法。那么我们可传入null来代替某个具体的对象

Math.max.apply(null, [1,2,5,3,4])

2-B call和apply用途

  • 改变this指向
  • Function.prototype.bind
  • 借用其他对象的方法