Javascript 中call() , applay()理解

call, apply都属于Function.prototype的一个方法,它是JavaScript引擎内在实现的,因为属于Function.prototype,所以每个Function对象实例,也就是每个方法都有call, apply属性.既然作为方法的属性,那它们的使用就当然是针对方法的了.这两个方法是容易混淆的,因为它们的作用一样,只是使用方式不同.

相同点: 两个方法产生的作用是完全一样的, apply:方法能劫持另外一个对象的方法,继承另外一个对象的属性.

不同点: 方法传递的参数不同

Function.apply(obj,args)

 Function.apply(obj,args)方法能接收两个参数
 obj:这个对象将代替Function类里this对象
 args:这个是数组,它将作为参数传给Function(args-->arguments

Function.call(obj,[param1[,param2[,…[,paramN]]]])

 Function.call(obj,[param1[,param2[,…[,paramN]]]])
 obj:这个对象将代替Function类里this对象
 params:这个是一个参数列表

使用场景:(参数数量是不是固定)

当你的参数是明确知道数量时,用 call;
而不确定的时候,用 apply,然后把参数 push 进数组传递进去。当参数数量不确定时;
函数内部也可以通过 arguments 这个数组来遍历所有的参数。

foo.call(this, arg1,arg2,arg3) 
== foo.apply(this, arguments)
== this.foo(arg1, arg2, arg3)
function people(){}
people.prototype={     
    name:"Tom",    
    say: function(){alert("my name is "+this.name);}
}
var Tom = new people;
Tom.say();

如果我们有一个对象Li = {name:”Li”},我们不想对它重新定义say方法,那么我们可以通过 call() 或 apply() 用 Tom 的say方法:

var Li = {name:"Li"}
Tom.say.call(Li);

call 和 apply 是为了动态改变this而出现的,当一个object没有某个方法,但是其他的有,我们可以借助call或apply用其它对象的方法来操作。

应用场景:
通过document.getElementsByTagName选择的dom 节点是一种类似array的array。它不能应用Array下的push,pop等方法。
我们可以通过:

var domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"),0);

这样domNodes就可以应用Array下的所有方法了。


猫吃鱼,狗吃肉,奥特曼打小怪兽。
有天狗想吃鱼了
猫.吃鱼.call(狗,鱼)
狗就吃到鱼了
猫成精了,想打怪兽
奥特曼.打小怪兽.call(猫,小怪兽)

ECMAScript6 引入了一套新的关键字用来实现 class。

JavaScript 仍然基于原型。这些新的关键字包括 class, constructor,static,extends 和 super。

class Polygon {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}

class Square extends Polygon {
  constructor(sideLength) {
    super(sideLength, sideLength);
  }
  get area() {
    return this.height * this.width;
  }
  set sideLength(newLength) {
    this.height = newLength;
    this.width = newLength;
  }
}

var square = new Square(2);

性能
在原型链上查找属性比较耗时,另外,试图访问不存在的属性时会遍历整个原型链。

要检查对象是否具有自己定义的属性,而不是其原型链上的某个属性,则必须使用所有对象从Object.prototype继承的 hasOwnProperty 方法。

扩展内置原型的唯一理由是支持JavaScript 引擎的新特性,如Array.forEach。

猜你喜欢

转载自blog.csdn.net/yy493004893/article/details/78791789