call 方法:
object.method.call(targetObj[, argv1, argv2, .....])
apply 方法:
object.method.apply(targetObj[, [argv1, argv2 .....]])
call 和 apply 的作用没有太大区别,仅是在调用时传递参数的方式不同,call 是按位置参数传递,apply 是传递一个参数数组。
call 和 apply 方法的作用如下:
以 targetObject 替换 object 引入当前的执行上下文中。
也就是说当使用 object.call(targetObj) 后,当前执行上下文中的 object 对象已被替换为 targetObj,后续执行将以 targetObj 所持有的状态属性继续执行。
借用 object 的方法:
targetObj 替换 object 的实例去调用相应的方法。
// Person 引用类型
function Person(name, age) {
this.name = name;
this.age = age;
// Person 的对象方法
this.getName = function () {
console.log(this.name);
}
}
// Person 的原型方法
Person.prototype.getInfo = function (joinStr, endLine) {
joinStr = joinStr || "-";
endLine = endLine || "!";
console.log(this.name + joinStr + this.age + endLine);
}
// Boy 引用类型
function Boy(name, age) {
this.name = name;
this.age = age;
}
var lilei = new Boy("lilei", 18);
// 调用 Person 的原型方法
// 注:原型方法和对象方法并不对等,虽然二者皆可被对象继承 但原型链上只有原型方法 没有对象方法
// 所以对象方法还是要以下面实例化一个对象的方式去调用,不能直接通过原型链访问
Person.prototype.getInfo.call(lilei, "-", "!");
Person.prototype.getInfo.apply(lilei, ["-", "!"]);
// 调用 Person 的对象方法
var person = new Person("none", 0);
person.getName.call(lilei);
person.getInfo.apply(lilei, ["-", "!"]);
Boy 虽然并没有定义 getName 对象方法,也没有 getInfo 原型方法,但我们可以方便的使用 call/apply 将 Person 的方法应用到 Boy 的实例上。call/apply 的语意其实是说 Person “喊” Boy 的实例过来使用自己的方法。
实现引用类型的继承:
Javascript 其实没有类这一概念,我们平时使用的 Array, Date, Math 等严格来说被称作 “引用类型”。我们可以方便的使用 call/apply 来实现引用类型的对象方法的继承,从而让代码更加的精简。
继承分为 对象继承 和 原型链继承 两部分
// Person 引用类型
function Person(name, age) {
this.name = name;
this.age = age;
// Person 的对象方法
this.getName = function () {
console.log(this.name);
}
}
// Person 的原型方法
Person.prototype.getInfo = function (joinStr, endLine) {
joinStr = joinStr || "-";
endLine = endLine || "!";
console.log(this.name + joinStr + this.age + endLine);
}
// ======================================================
// Boy 引用类型
function Boy(name, age) {
// 对象冒充继承
// 将 Person 的对象成员继承过来
Person.call(this, name, age);
}
// 原型链继承
// 将 Person 的原型属性继承过来
Boy.prototype = new Person();
// ======================================================
var lilei = new Boy("lilei", 18);
lilei.getName();
lilei.getInfo();
console.log(Boy.prototype.getInfo);
注意这里 call/apply 只是继承父原型的对象方法,原型方法还需要单独的继承一次。
平时开发中比较经典的用例就是:
Array.prototype.slice.call(document.getElementsByTagName("p"));
如上代码会返回一个DOM元素数组,document.getElementsByTagName("p") 获取到的并不是真正意义上的数组,没办法使用 pop 或 push 等方法,Array.prototype.slice 的实现大致如下:
Array.prototype.slice = function (start, end) {
var temp = [];
var start = start || 0;
var end = end || this.length - 1;
for (var i = start; i <= end; i ++) {
temp.push(this[i]);
}
return temp;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。