根据javascript高级程序设计第三版 “事实上,传递参数并非apply()和call()真正用武之地,他们真正强大的地方是能够扩充函数赖以运行的作用域“ && “扩充作用域的最大好处,就是对象不需要与方法有任何耦合关系”
Chapter 1
//A有方法,B没有,通过call B可以引用A的方法
function cat(){
}
cat.prototype={
food:"fish",
say: function(word){
alert("I love "+this.food+" and talk "+word);
}
}
var blackCat = new cat;
//blackCat.say('miaomiao');
var whiteDog = {food:"bone"}
blackCat.say.call(whiteDog,'wangwang');
//blackCat.say.apply(whiteDog,['wangwang']);
这里blackCat继承了Cat的say方法,而whiteDog如果在不想定义say方法的情况下使用,就需要call的出现了,这里whiteDog可是引用到blackCat的say方法
Chapter 2
// call实现继承
var Parent = function(){
this.name = "yjc";
this.age = 22;
}
var child = {};
console.log(child);//Object {} ,空对象
Parent.call(child);
console.log(child); //Object {name: "yjc", age: 2}
通过call来实现属性的继承
Chapter 3
// call将参数转为数组
function exam(a, b, c, d, e) {
// 先看看函数的自带属性 arguments 什么是样子的
console.log(arguments);
// 使用call/apply将arguments转换为数组, 返回结果为数组,arguments自身不会改变
var arg = [].slice.call(arguments);
console.log(arg);
}
exam(2, 8, 9, 10, 'guguji');
// result:
// { '0': 2, '1': 8, '2': 9, '3': 10, '4': 'guguji','length':5 }
// [ 2, 8, 9, 10, 3 ]
[].slice.call()这种方法可以将带有length的key为自然数的json转换为数组,也常常使用该方法将DOM中的nodelist转换为数组。
[].slice.call( document.getElementsByTagName('li')
call和apply功能相同,只是写法不一样而已。
fun.call(this,1,2,'dukuan');
fun.apply(this,[1,2,'dukuan']);//参数以数组的方式传入
e.g. Math.max(a,b,…,x,y)函数用于取若干值(不是只能比较两个)中的最大值,所以求一个数组中([1,4,5,2,65,7,5])的最大值可以借助apply
var arr=[1,2,2,1,4,5,6,6,8,9,55];
var Max=Math.max.apply(null,arr);//最大值为55
bind vs call,apply
MDN bind的定义是:
The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
bind方法创建一个新函数,当被调用时会改变this的值以及传入一串新函数调用的预设参数。
偶发现bind和call,apply的一个不同是bind会返回一个新函数并且带有一些预设参数(不会执行)而call,apply会调用这个函数。
bind的两大功能,改变this和预设参数。
为了兼容低版本浏览器bind可以重写:
Function.prototype.Bind = function(index){
var that = this;
var arg = Array.prototype.slice.call(arguments,1)
return function(){
var arg1 = Array.prototype.slice.call(arguments);
that.apply(index,arg.concat(arg1))
}
}