http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance.html
先对apply方法进行了解
文档中说apply方法是应用某一对象的一个方法,用另一个对象替换当前对象。
语法:
oldobj.apply(newobj)
我认为:简单来说就是让newobj来指向oldobj中的this指向
例:
var obj={"name":"maomao","age":20};
function test(){
alert(this);
//console.log(this.name); //可以尝试调一下对象的内容
}
// test(); // [object Window]
test.apply(obj); //[object Object]
console.log(test.apply(obj)) //undefined 无返回值
//上面在执行test.apply(obj)发生了将obj传给test函数,并且调用test,当执行console.log(this.name);
语句时则会访问该obj对象的name属性,因此会弹出”maomao”
总结:函数在正常调用的时候,this的指向都是确定的(who调用该函数则this指向谁)。使用apply方法就可以修改this的指向问题,并且可以调用该方法(如上面中执行了test.apply(obj)会调用test方法,然后方法里的this指向的是obj对象)
继承的实现
//动物对象构造函数
function Animal(){
this.species = "动物";
}
//"猫"对象的构造函数
function Cat(name,color){
this.name = name;
this.color = color;
}
方法一:构造函数的绑定
使用call或apply方法,将父对象的构造函数绑定在子对象上。即在子对象构造函数中加一行:Animal.apply(this, arguments)
function Cat(name,color){
Animal.apply(this, arguments);
this.name = name;
this.color = color;
}
var cat1 = new Cat("大毛","黄色");
alert(cat1.species); // 动物
上面的”Animal.apply(this, arguments);”发生了什么?创建cat1实例时,会调用Cat构造函数,然后会调用Animal函数(此时函数里的this指向的是cat1实例,并且将你赋的初始值arguments对象传递给这个函数),然后执行this.species 所以cat1实例会创建species属性。
方法二:prototype模式 —!!!有点不懂
先探讨prototype属性与constructor属性的区别
Javascript规定,每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。
function Animal(){
this.species = "动物";
}
function Cat(name,color){
this.name = name;
this.color = color;
}
var cat1 = new Cat("大毛","黄色");
console.log(cat1.constructor); //function Cat(name,color){this.name=name;this.color=color;}
console.log(Animal.constructor); //function Function() { [native code] }
console.log(cat1.prototype); //undefined
console.log(Cat.prototype); //Object {constructor: function Cat(name,color){this.name=name;this.color=color;}}
console.log(Cat.prototype.constructor); //function Cat(name,color){this.name=name;this.color=color;}
console.log(cat1.constructor==Cat.prototype.constructor); //true
从上面得出每个实例对象和构造函数都有construct属性,但是只有构造函数有prototype属性而实例对象没有prototype属性
下面是我按照上面的代码自己画的图,不知道理解的对不对。。。
上面说到给构造函数的prototype属性所指向对象添加方法或属性 能继承给 构造函数创建的实例对象
如果"猫"的prototype对象,指向一个Animal的实例,那么所有"猫"的实例,就能继承Animal了。
//Cat的prototype对象指向一个Animal的实例。
Cat.prototype = new Animal();
//Cat的prototype对象的构造函数指向了Cat
Cat.prototype.constructor = Cat;
var cat1 = new Cat("大毛","黄色");
alert(cat1.species); // 动物
方法三:直接继承prototype
先理解一下下面的
function Animal(){ }
Animal.prototype.species = "动物";
//上面在创建Animal对象实例的时候会给每个对象共享一份共有的属性species,所以每一个对象都能访问到这个属性。注意:这里是所有对象都共享,共享,共享!!!
var animal1=new Animal();
console.log(animal1.species); //动物
既然Animal.prototype.species = "动物";代表所有对象共享的话,就可以近似的(理解)认为当使用Animal创建对象实例后都有一个属性species,即原型对象中的东西会被创建的实例继承(也就是说你创建对象后这些在原型对象中封装好的东西会直接给实例拿去用)
创建对象后这些在原型对象中封装好的东西(其中包括构造函数)会直接给实例拿去用。其中构造函数会对实例化的对象进行初始化赋值
//Cat的prototype对象,然后指向Animal的prototype对象,这样就完成了继承。
Cat.prototype = Animal.prototype;
Cat.prototype.constructor = Cat;
var cat1 = new Cat("大毛","黄色");
alert(cat1.species); // 动物
/*对象的指向可以用箭头来指向。如:var a=new Person(); //a指向了那个对象。所以上面可以说是Cat.prototype指向了Animal.prototype,然后第二句代表在Animal.prototype对象中创建了constructor属性。然后创建实例,Cat.prototype指向的对象Animal.prototype里面的属性和方法在实例cat1中都能访问的到*/
方法四:利用空对象作为中介
方法五:拷贝继承