目录
一、知识回顾:
在学习新知识之前我们简单回顾一下 call、apply、bind方法的使用:
call和apply的共同点是能够改变函数的执行时的上下文,将一个对象的方法交给另一个对象来执行,并且是立即执行的;bind() 方法创建一个新的函数,在调用时设置 this 关键字为提供的值。
1、call方法的使用:
a:语法:
Function.call(obj,[param1[,param2[,…[,paramN]]]])
b:注意点:
(1)调用call方法的必须是函数。
(2)call 的第一个参数,是一个对象。 Function 的调用者,将会指向这个对象。如果不传,则默认为全局对象 window。
(3)第二个参数开始,可以接收任意个参数。每个参数会映射到相应位置的 Function 的参数上。但是如果将所有的参数作为数组传入,它们会作为一个整体映射到 Function 对应的第一个参数上,之后参数都为空。
c:代码实例:
var person = {
fullName:function (city,country) {
return this.firstName+" "+this.lastName+","+city+","+country;
}
};
var person1 = {
firstName:"1",
lastName:"2"
};
var person2 = {
firstName:"3",
lastName:"4"
};
var x = person.fullName.call(person1,"HeNan","China");
console.log(x);
2、apply方法的使用:
a:语法:
Function.apply(obj[,argArray])
b:注意点:
(1)它的调用者必须是函数 Function,并且只接收两个参数,第一个参数的规则与 call 一致。
(2)第二个参数,必须是数组或者类数组,它们会被转换成类数组,传入 Function 中,并且会被映射到 Function 对应的参数上。这也是 call 和 apply 之间,很重要的一个区别。
c:代码实例:
var person = {
fullName:function (city,country) {
return this.firstName+" "+this.lastName+","+city+","+country;
}
};
var person1 = {
firstName:"1",
lastName:"2"
};
var person2 = {
firstName:"3",
lastName:"4"
};
var y = person.fullName.apply(person2,["HeNan","China"]);
console.log(y);
3、bind方法的使用:bind()
最简单的用法是创建一个函数,使这个函数不论怎么调用都有同样的this值。
a:语法:
Function.bind(thisArg[, arg1[, arg2[, ...]]])
b:注意点:
bind 方法的返回值是函数,并且需要稍后调用,才会执行
c:代码:
function add(a,b){
console.log(a+b);
}
function sub(a,b) {
console.log(a-b);
}
add.bind(sub,5,3)();
二、借用构造函数实现继承:
1、 在解决原型中包含引用类型值所带来问题的过程中,开始使用一种叫做借用构造函数(伪造对象/经典继承)的技术。基本思想:在子类型构造函数的内部调用超类型构造函数。
function SuperType() {
this.colors = ["red","blue","green"];
}
function SubType() {
// 继承了SuperType
SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push("black");
console.log(instance1.colors);
var instance2 = new SubType();
console.log(instance2.colors);
解释:
代码中写注释的是借用了超类型的构造函数。通过使用call()方法(或apply()方法),改变该函数this的指向。我们实际上是在新创建的函数SubType实例的环境下调用了SuperType构造函数。这样一来,就会在新SubType对象上执行SuperType()函数中定义的所有对象初始化代码。结果,SubType的每个实例就都会具有自己的colors属性的副本。
2、借用构造函数的优势:可以在子类型构造函数中向超类型构造函数传递参数。
function SuperType2(name) {
this.name = name;
}
function SubType2(){
// 继承了SyperType2,同时还传递了参数
SuperType2.call(this,"萝卜头");
// 实例属性
this.age = 29;
}
var instance2 = new SubType2();
console.log(instance2.name);
console.log(instance2.age);
以上代码中的SuperType2只接受一个参数name,该参数会直接赋给一个属性。在SubType2构造函数内部调用SuperType2构造函数时,实际上是为SubType2的实例name属性。
三、借用构造函数的问题:
无法避免构造函数模式存在的问题,方法都在构造函数中定义,因此函数复用就无从谈起。在超类型的原型中定义的方法,对子类型而言也是不可见的,结果所有类型都只能使用构造函数模式。
注:内容参考《JavaScript高级程序设计》