标签:浅拷贝 this his 构造器 2d图形 接受 ext == type
1)原型链
①原型链示例
function Shape() {
this.name = ‘shape‘;
this.toString = function(){
return this.name;
}
}
function TwoDshape () {
this.name = ‘2D shape‘;
}
function Triangle (side,height) {
this.name = ‘Triangle‘;
this.side = side;
this.height = height;
this.getArea = function () {
return this.side * this.height / 2;
}
}
TwoDshape.prototype = new Shape();
Triangle.prototype = new TwoDshape(); //用new新建对象实体,并赋值覆盖该对象的原型
TwoDshape.prototype.constructor = TwoDshape;
Triangle.prototype.constructor = Triangle;
var my = new Triangle(5,10);
my.getArea(); //25
console.log(my.toString());//继承的方法,具体步骤(遍历my对象属性没有找到,接着查看my.__proto__所指向的对象,即new TwoDshape()创建的实体,
//依然没找到,又继续查找该实体的__proto__所指向的对象,即new Shape()所创建的实体,找到toString方法,并在my对象中被调用,this指向my)
//通过instanceof操作符,我们可以验证my对象同时是上面三个构造器的实例
my instanceof Shape; //true
my instanceof TwoDShape; //true
my instanceof Triangle; //true
//我们也可以用其他两个构造器来创建对象,用new TwoDshape()所创建的对象也可以获得继承自Shape()的toString()方法
var td = new TwoDshape();
td.constructor === TwoDshape; //true;
td.toString(); // 2D shape
var s = new Shape();
s.constructor === shape; // true;
②将共享属性迁移到原型中去
function Shape(){this.name=‘shape‘}//使用new Shape()新建对象,每个实体都有全新的属性并占用独立空间
function Shape(){};Shape.prototype.name=‘shape‘;//属性移到原型后,使用new新建对象时,不再含自己独立的这个属性
2)只继承于原型
Triangle.prototype=Shape.prototype;//减少继承方法的查询步骤 Triangle.prototype.name=‘Triangle‘;//修改子对象原型后父对象原型也随即被改,即再new Shape()新建对象时,新对象name为‘Triangl
②临时构造器——new F()
function Shape() {}
Shape.prototype.name = "shape";
Shape.prototype.toString = function () {
return this.name;
}
function TwoDshape() {}
var F = function () {};
F.prototype = Shape.prototype;
TwoDshape.prototype = new F();
TwoDshape.prototype.constructor = TwoDshape;
TwoDshape.prototype.name = ‘2D shape‘;
function Triangle(side, height) {
this.side = side;
this.height = height;
}
var F = function () {};
F.prototype = TwoDshape.prototype;
Triangle.prototype = new F();
Triangle.prototype.constructor = Triangle;
Triangle.prototype.name = ‘Triangle‘;
Triangle.prototype.getArea = function () {
return this.side * this.height / 2;
}
var my = new Triangle (5,10);
alert(my.getArea());
//通过这种方法,我们仍然能保持住原型链
my._proto_ === Triangle.prototype; //true
my._proto_.constructor === Triangle; //true
my._proto_._proto_ === TwoDshape.prototypr; //true
my._proto_._proto_._proto_.constructor === Shape;_ //true
//并且父对象的属性不会被子对象覆盖:
var s = new Shape();
s.name; // shape
//calling toString()
"I am a" + new TwoDshape(); //I am a 2D shape
3)uber—子对象访问父对象的方式
function Shape(){}
Shape.prototype.name=‘shape‘;
Shape.prototype.toString=function(){
var const = this.constructor;
return const.uber
? this.const.uber.toString() + ‘,‘ + this.name
: this.name;
}
function TwoDShape(){
var F=function(){}
F.prototype=Shape.prototype;
TwoDShape.prototype=new F();
TwoDShape.prototype.constructor=TwoDShape;
TwoDShape.uber=Shape.prototype;
TwoDShape.prototype.name=‘2D shape‘;
function Triangle(side,height){
this.side=side;
this.height=height;
}
var F=function(){}
F.prototype=TwoDShape.prototype;
Triangle.prototype=new F();
Triangle.prototype.constructor=Triangle;
Triangle.uber=TwoDShape.prototype;
Triangle.prototype.name=‘triangle‘;
Triangle.prototype.getArea=function(){return this.side*this.height/2};
var my=new Triangle(5,10)
console.log(my.toString());//shape,2D shape,triangle
4)将继承部分封装成函数
function extend (Child,Parent) {
var F = function () {};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
Child.uber = Parent.prototype;
}
extend(TwoDsgape,Shape);
extend(Triangle,TwoDshape);
5)属性拷贝
/*属性拷贝执行的是对象原型的逐一拷贝,而非简单的原型链查询。
所以需要特别注意的是:
这种方法仅适用于包含基本数据类型的对象,
所有的对象类型(包括函数和数组)都是不可复制的,
因为他们只支持引用传递
*/
function extend2(Child,Parent){
var p = Parent.prototype;
var c = Child.prototype;
for(var i in p){
c[i] = p[i];
}
c.uber = p ;
}
6)小心处理引用拷贝
var A=function(){},B=function(){};
A.prototype.stuff=[1,2,3];
A.prototype.name=‘a‘;
extend2(B,A);//让B继承A使用方法二
B.prototype.name+=‘b‘;//ab,A.prototype.name依然为a,因为拷贝的是值
B.prototype.stuff.push(4);//此时A和B原型上的stuff同时被修改,因为拷贝的是应用
B.prototype.stuff=[‘a‘,‘b‘,‘c‘]//如果完全重写事情就不一样了,A为原来,B为新的
7)对象之间的继承(不使用构造器)
function extendCopy (p) {
var c = {};
for (var i in p){
c[i] = p[i];
}
c.uber = p;
return c;
}
var shape ={
name = ‘shape‘,
toString :function () {
return this.name;
}
}
var twoDee = extendCopy(shape);
twoDee.name = ‘2D shape‘;
twoDee.toString = function () {
return this.uber.toString() + ‘,‘ + this.name;
}
//下面我们让triangle对象继承一个2D图形对象
var triangle = extendCopy(twoDee);
triangle.name = ‘Triangle‘
triangle.getArea = function () {
return this.side * this.height / 2;
}
//使用triangle
triangle.side = 5;
triangle.height = 10;
triangle.getArea(); //25
triangle.toString(); // shape,2D shape,Triangle
8)深拷贝(当遇到对象类型时,再次调用拷贝)
function deepCopy(p,c){
c = c || {};
for (var i in p){
if(p.hasOwnProperty(i)){
if(typeof p[i] === ‘object‘){
c[i] = Array.isArray(p[i]?[]:{});
deepCopy(p[i],c[i]);
}else{
c[i] = p[i]
}
}
}
return c;
}
var parent = {
numbers:[1,2,3],
letters:[‘a‘,‘b‘,‘c‘],
obj:{
prop : 1
},
bool : true
};
//我们分别用深拷贝和浅拷贝测试一下,就会发现两者的不同。
//在深拷贝中,对对象的numbers属性进行更新不会对原对象产生影响。
var mydeep = deepCopy(parent);
var myshallow = extendCopy(parent);
mydeep.numbers.push(4,5,6);
mydeep.numbers //[1,2,3,4,5,6]
parent.numbers //[1,2,3]
myshallow.numbers.push(10);
myshallow.numbers //[1,2,3,10]
parent.numbers //[1,2,3,10]
9)object()(用object函数来接受父对象,并返回一个以该对象为原型的新对象)
function object(o){
var n;
function F(){}
F.prototype=o;
n=new F();
n.uber=o;
return n;
}//这个函数与extendcopy基本相同
10)原型继承与属性拷贝的混合应用
function objectplus(o,stuff){
var n;
function F(){}
F.prototype=o;
n=new F();
n.uber=o;
for(var i in stuff){n[i]=stuff[i]}
return n;
}//两对象o用于继承,stuff用于拷贝方法与属性
11)多重继承(一个对象中有不至一个父对象的继承)
function multi(){
var n={},stuff,j=0,len=arguments.length;
for(j=0;i<len;j++){
stuff=arguments[j];
for(var i in stuff){n[i]=stuff[i]}
}
return n;
}//内层循环用于拷贝属性,外层循环用于遍历多个父对象参数,若有相同属性后面替代之前
12) 寄生式继承
13)构造器借用
待续...
标签:浅拷贝 this his 构造器 2d图形 接受 ext == type
原文地址:http://www.cnblogs.com/yechanglv/p/6937966.html