JS继续
原型链
组织函数、原型、实例的关联
每一个组织函数都有一个原型对象,原型对象包括一个指向组织函数的指针,而实例包括一个指向组织函数的指针。
原型链的构建是经由历程将一个范例的实例赋值给另一个组织函数的原型完成。
function SuperType(){
this.property=true;
}
SuperType.prototype.getSuperValue=function () {
return this.property;
};
function SubType(){
this.subproperty=false;
}
//继续SuperType
SubType.prototype=new SuperType();
SuperType.prototype.getSubValue=function () {
return this.subproperty;
}
var instance=new SubType();
console.log(instance.getSubValue()); //false
console.log(instance.getSuperValue()); //true
SubType继续SuperType是经由历程建立SuperType实例,并将该实例赋给SubType.prototype完成的。实质是重写原型对象,代之以一个新范例的实例。
instance指向SubType的原型,SubType的原型又指向SuperType的原型。要注意的是instance.constructor如今指向的是SuperType,应为SubType的原型指向了SuperType的原型,而该原型对象的constructor属性指向的SuperType。
原型搜刮机制
挪用instance.getSuperValue()会阅历一下三个步骤:
1)搜刮实例
2)搜刮SubType.prototype
3)搜刮SuperType.prototype,末了一步才会找到该要领。在找不到属性或要领的情况下,搜刮历程总要一环一环地前行到原型链末尾为止。
肯定原型与实例的关联
1.instanceof
instance instanceof Object
2.isPrototypeOf
Object.prototype.isPrototypeOf(instance)
定义要领
1.子范例须要掩盖超范例中的某个要领,或须要增加超范例中不存在的某个要领。给原型增加要领的代码要放在替代原型的语句背面。
function SuperType(){
this.property=true;
}
SuperType.prototype.getSuperValue=function () {
return this.property;
};
function SubType(){
this.subproperty=false;
}
//继续SuperType
SubType.prototype=new SuperType();
//增加新要领
SuperType.prototype.getSubValue=function () {
return this.subproperty;
}
//重写超范例中的要领
SubType.prototype.getSuperValue=function () {
return false;
}
var instance=new SubType();
console.log(instance.getSuperValue());
2.经由历程原型链完成继续时,不能运用对象字面量建立原型要领。如许会重写原型链。
function SuperType(){
this.property=true;
}
SuperType.prototype.getSuperValue=function () {
return this.property;
};
function SubType(){
this.subproperty=false;
}
//继续SuperType
SubType.prototype=new SuperType();
SubType.prototype={
getSubValue:function () {
return this.subproperty;
}
};
var instance=new SubType();
console.log(instance.getSuperValue()); //error
以上代码先把SuperType的实例赋值给原型,紧接着又将原型替代成一个对象字面量。因为如今的原型包括的是一个Object实例,而非SuperType的实例。因而,本来的SuperType和SubType之间的原型链被割断。
原型链的题目
1.包括援用范例的原型属性会被一切实例同享。
function SuperType(){
this.nums=[1,2];
}
function SubType(){
}
//继续SuperType
SubType.prototype=new SuperType();
var instance=new SubType();
instance.nums.push(5);
console.log(instance.nums); //[1,2,5]
var instance1=new SubType();
instance1.nums.push(0);
console.log(instance1.nums); //[1,2,5,0]
2.建立子范例的实例时,不能向超范例的组织函数中通报参数。
借用组织函数(捏造对象/典范继续)
在子范例组织函数内部挪用超范例组织函数。
function SuperType(){
this.nums=[1,2];
}
function SubType() {
SuperType.call(this);
}
SubType.prototype=new SubType();
var instance=new SubType();
instance.nums.push(3);
console.log(instance.nums);
var instance2=new SubType();
console.log(instance2.nums);
经由历程运用call()要领(或apply()要领),在新建立的SubType实例的环境下挪用了SuperType组织函数。如许就会在新SubType对象上实行SuperType函数中定义的一切对象初始化代码。SubType的每一个实例都邑具有本身的nums属性的副本。
1.通报参数
子范例组织函数向超范例组织函数通报参数。
function SuperType(name){
this.name=name;
this.school=['whu'];
}
function SubType() {
SuperType.call(this,"张三");
//实例属性
this.age=20;
}
var instance=new SubType();
instance.school.push('hhu');
console.log(instance.name);
console.log(instance.age);
console.log(instance.school);
var instance2=new SubType();
console.log(instance2.school);
2.存在的题目
要领都在组织函数中定义,函数没法复用;
在超范例的原型中定义的要领,关于子范例而言是不可见的,那末一切范例都只能运用组织函数情势。
组合继续
运用原型链完成对原型属性和要领的继续,而经由历程组织函数来完成实例属性的继续。
function SuperType(name){
this.name=name;
this.city=['武汉','杭州'];
}
SuperType.prototype.sayName=function () {
console.log(this.name);
}
function SubType(name,age) {
//继续属性
SuperType.call(this,name);
//实例属性
this.age=age;
}
//继续要领
SubType.prototype=new SuperType();
SubType.prototype.constructor=SubType;
SubType.prototype.sayAge=function () {
console.log(this.age);
}
var instance1=new SubType('chen',18);
instance1.city.push('北京');
console.log(instance1.city);
instance1.sayName();
instance1.sayAge();
var instance2=new SubType('huang',19);
console.log(instance2.city);
instance2.sayName();
instance2.sayAge();
原型式继续
function object(o){
function F(){}
F.prototype=o;
return new F();
}
在object函数内部,先建立一个暂时性的组织函数,然后将传入对象作为这个组织函数的原型,末了返回了这个暂时范例的一个新实例。实质上是object()对传入个中的对象实行了一次浅复制。
var navy={
name:'水师',
weapon:['航母','驱逐舰']
};
function object(o){
function F() {
}
F.prototype=o;
return new F();
}
var navy1=object(navy);
navy1.name="俄罗斯";
navy1.weapon.push('巡洋舰');
var navy2=object(navy);
navy2.name='美国';
navy2.weapon.push('护卫舰');
console.log(navy.weapon);
ECMAScript5新增Object.create()要领范例了原型式继续,吸收两个参数:一个是作用于新对象原型的对象,(可选)二是一个新对象定义分外属性的对象.
var car={
name:'奔驰',
weapon:['车轮','发动机']
};
var car1=Object.create(car,{
name:{
value:'宝马'
}
});
console.log(car1.name);
原型式的题目依然是包括援用范例的属性会一切实例被同享
寄生式继续
function object(o){
function F() {
}
F.prototype=o;
return new F();
}
function createAnother(original) {
var clone=object(original); //经由历程挪用函数建立一个新对象
clone.sayHi=function () { //以某种体式格局加强这个对象
console.log('hi');
};
return clone; //返回对象
}
var person={
name:'coder',
ability:['Java','R']
};
var another=createAnother(person);
another.sayHi();
寄生式的题目依然是不能做到函数复用
寄生组合式继续
组合继续最大的题目就是会挪用两次超范例组织函数:一次是建立子范例原型时刻,一次是在子范例组织函数内部。
function SuperType(name){
this.name=name;
this.city=['南京','姑苏'];
}
SuperType.prototype.sayName=function () {
console.log(this.name);
}
function SubType(name,age) {
SuperType.call(this,name);//第二次挪用SuperType
this.age=age;
}
SubType.prototype=new SuperType(); //第一次挪用SuperType
SubType.prototype.constructor=SubType;
SubType.prototype.sayAge=function () {
console.log(this.age);
}
在第一次挪用SuperType组织函数时,SubType.prototype会获得两个属性:name和colors;都是SuperType的实例属性,只不过如今位于SubType的原型中.当挪用SubType组织函数,又会挪用一次SuperType的组织函数,这一次又在新对象上建立了实例属性name和colors.因而这两个属性就屏障了原型中的两个同名属性.
寄生组合式继续经由历程借用组织函数来继续属性,经由历程原型链的混成情势来继续要领.其基本思想是:没必要为了指定子范例的原型而挪用超范例的组织函数,所须要的只是超范例原型的一个副本.实质上,就是运用寄生式继续来继续超范例的原型,然后再讲效果指定给子范例的原型.
function inheritPrototype(subType,superType){
var prototype=object(superType.prototype); //建立对象
prototype.constructor=subType; //加强对象
subType.prototype=prototype; //指定对象
}
inheritPrototype
函数接收两个参数:子范例组织函数、超范例组织函数
1.建立超范例原型的一个副本
2.为建立的副本增加constructor属性,填补因重写原型而落空的默许的constructor属性.
3.将新建立的对象(即副本)赋值给子范例的原型.
function SuperType(name){
this.name=name;
this.city=['南京','姑苏'];
}
SuperType.prototype.sayName=function () {
console.log(this.name);
}
function SubType(name,age) {
SuperType.call(this,name);//第二次挪用SuperType
this.age=age;
}
inheritPrototype(SubType,SubType);
SubType.prototype.sayAge=function () {
console.log(this.age);
}
上述只挪用了一次SuperType组织函数,并因而避免了在SubType.ptototype上建立没必要要的、过剩的属性.与此同时,原型链还能坚持稳定.