原型继承的几种方式

1. 第一种方式-----在函数Itouch中可以把函数Ipod函数赋值给this.ss,这个this指向的便是Itouch这个函数,待this.ss();执行之后,Itouch便有了playmusic 方法

function Ipod(){
		this.playmusic = function(){
			console.log("paly music....");
		}
	}
function Itouch(){
		this.ss = Ipod;
		this.ss();
		this.playgame = function(){
			console.log("play game....");
		}
}
new Itouch().playmusic() //调用Ipod里面的方法
console.log(new Itouch());如图所示
1
2
3
4
5
6
7
8
9
10
11
12
13
14

2. 第二种方式----利用call(函数不可独立存在,总是要依附于某个对象,不管是自定义的,还是全局的,因此函数的执行,总是这样)方法,

obj.func();  //表示对象obj调用了func

但我们也可以反过来:

func.call(obj);  //函数func被调用了,通过obj

如果需要传参数:

func.call(obj, param1, param2,....);
比如  这样的方式
function Father(p1,p2,p3,p4){
     this.money = 1000000;
}
function Son(v1,v2,v3,v4){
     Father.call(this, v1, v2, v3, v4);
}

call改变调用函数的对象,Ipod.call(this);把Ipod对象变成了Itouch,故Itouch可以使用Ipod里面的方法

function Ipod(){
    this.playmusic = function(){
        console.log("paly music....");
    }
}
function Itouch(){
    Ipod.call(this);
    this.playgame = function(){
        console.log("play game....");
    }
}
console.log(new Itouch());如图所示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

3. 第三种方式----apply与call方式类似。只是apply可加入参数的方式是数组,这个可以利用arguments类数组对象,参数传入都保存在了arguments这个类数组对象中

function Father(p1,p2,p3,p4){
    this.money = 1000000;
}
function Son(v1,v2,v3,v4){
    Father.apply(this, [v1, v2, v3, v4]);
}
// 可以再改造一下:
function Son(){
    Father.apply(this, arguments);
}
1
2
3
4
5
6
7
8
9
10

4. 第四种方式-----原型继承,可以扩展函数系统的能力,原型属性一般不可以更改,但是可以用原型覆盖原来的属性和方法

function Ipod(){
}
Ipod.prototype.playmusic = function(){
    console.log("paly music....");
}
function Itouch(){
    this.playgame = function(){
        console.log("play game....");
    }
}
Itouch.prototype = new Ipod();  //那么Itouch便可以使用Ipod中的原型方法了

Itouch.prototype.playmusic(); //结果便是play music...
1
2
3
4
5
6
7
8
9
10
11
12
13

5 第五种方式----

Object.create 
// 创建对象的一种新形式:
var father = {
     money: 999999
}
var son = Object.create(father);
son.money; //999999
//不要误以为这是在复制对象,实际上这是在继承,因为father对象的内容被存入了son对象的原型当中
1
2
3
4
5
6
7
8

举例:

function Father(){
    this.name = "王健林";
    this.age = 60;
}
Father.prototype = {
    wanda : function(){
        return "$99999999999";
    }
}
1
2
3
4
5
6
7
8
9

//以前的写法,大概是这样:

//Son.prototype = new Father();
1

//缺点很明显就是,连名字和年龄都继承了,其实我们并不想要这些

//下面的写法,带来了一定的好处,Son的原型的原型是Fahter的原型,同样是原型链继承的效果。

Son.prototype = Object.create(Father.prototype);
function Son(){    
     this.name = "王思聪";
     this.age = 30;
}
new Son().wanda();
1
2
3
4
5
6

//要注意这个方法不能实现对象拷贝,因为这里是原型的赋值,并且生成了新对象,不是简单的属性复制

例如:

var a = {
     text1 : "abc"
}
var b = {
     text2 : "def"
}
b = Object.create(a); //结果b虽然继承了a,但原有内容被覆盖了!

b.text1; //abc
b.text2; //undefined
1
2
3
4
5
6
7
8
9
10

解决办法如下:

var b = Object.create(a, {
     text2 : {
         value : "def" 
     }
})
1
2
3
4
5

原型有两种访问方式

Itouch.prototype.playgame();

var it = new Itouch();
it.__proto__.playgame();
1
2
3
4

通过prototype或者__proto__的方式可以修改原型

prototype 说的是构造函数和原型对象之间的关系, proto 说的是实例对象和原型对象之间的关系

用的多的还是混合继承

function Father(){
     
}
Father.prototype.liaomei = function(){

}
Son.prototype = new Father();
function Son(){
    Father.apply(this,arguments);    
}
1
2
3
4
5
6
7
8
9
10