0.为什么要使用继承
方法可能功能相似,但是不是同一个方法(没有指向同一块内存,会造成内存浪费)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
</body>
<script>
function Person(name,age){
this.name=name;
this.age=age;
this.say=function(){}
}
var p1=new Person();
var p2=new Person();
//p1对象和p2对象的say方法是否是同一个方法:false
console.log(p1.say===p2.say);
//由于say方法可能功能相似,但是不是同一个方法(没有指向同一块内存,会造成内存浪费)
//解决方案:把say方法写在他们共同的(父对象)中
//其实他们共同的父对象,就可以通过:Person.prototype来获取
//-->只要把say方法写在Person.prototype中,那么say方法就是同一个方法
Person.prototype.run=function(){
console.log('时速500KM');
}
//此时p1和p2都可以访问到run方法
p1.run();
p2.run();
//验证p1.run和p2.run是否是同一个方法?
console.log(p1.run == p2.run); //指向同一个方法,这种方法避免了内存的浪费
console.log(p1.run == Person.prototype.run);
//true
var p3=new Person();
console.log(p3.run == p1.run); //true
console.log(p3.run === p1.run);//true
//结论:只要往某个构造函数的prototype对象中添加某个属性、方法,那么这样的属性、方法都可以被所有的构造函数的实例所共享
//==>这里的【构造函数的prototype对象】称之为原型对象
// Person.prototype是 p1 p2 p3 的原型对象
// Person.prototype是Person构造函数的【实例】的原型对象
//猜猜看?
// Person的原型对象是谁呢?
// -->首先要知道Person的构造函数:-->Function
// -->所以Person的原型对象是:Function.prototype
// p1的原型对象是谁呢?
// -->首先要知道p1是谁创建的? -->Person
// -->所以p1的原型对象时: Person.prototype
</script>
</html>
0.1继承方法实现1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
</body>
<script>
function Dog(){
}
var d1=new Dog();
//为了让d1有一个叫的方法,
//不行:d1.say=function(){}
//正确:
Dog.prototype.say=function(){
console.log('汪汪汪');
}
//继承的第一种实现方式:原型链继承
</script>
</html>
0.2继承方法实现2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
</body>
<script>
function Cat(name){
this.name=name;
}
var tom=new Cat("汤姆");
//目的:把say方法放在tom的原型对象中(Cat.prototype)
Cat.prototype.say=function(){}
//问题:
Cat.prototype.s1=function(){}
Cat.prototype.s2=function(){}
Cat.prototype.s3=function(){}
Cat.prototype.s4=function(){}
Cat.prototype.s5=function(){}
//通过上面的方式,给tom的原型对象添加了好多方法,也就是让tom拥有了好多方法,但是代码产生了不少的冗余(重复)
//-->为了减少这种重复,改良版:
Cat.prototype = {
a1:function(){},
a2:function(){},
a3:function(){},
a4:function(){},
a5:function(){}
}
console.log(tom.s1); //可以访问
console.log(tom.a1); //undefined
//原因:tom对象在创建的时候已经有了一个确定的原型对象,就是旧的Cat.prototype
//由于Cat.prototype后面被重新赋值,但是tom对象的原型对象却没有改变,所以tom对象并不能访问到新原型对象中的a1-a5方法
//如何解决这个问题?
//-->先改变原型、再创建对象
//继承的第一种实现方式:原型链继承
</script>
</html>
1.原型链继承
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
</body>
<script>
function Tiger(){
}
Tiger.prototype={
a:function(){
},
b:function(){
}
}
//创建tiger实例,此时的tiger实例的原型对象是新原型,所以tiger可以访问到新原型中的属性和方法(a/b)
var tiger=new Tiger();
console.log(tiger.a);
console.log(tiger.b);
</script>
</html>
2.拷贝继承
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
</body>
<script>
//1、已经拥有了o3对象
var o3={gender:"男",grade:"大四",group:"第五组",name:"itwangyangcoder"};
//2、创建一个o3对象的拷贝(克隆):for...in循环
var o4={};
//a、取出o3对象中的每一个属性
for (var key in o3) {
//key就是o3对象中的每一个属性
//b、获取到对应的属性值
var value = o3[key];
//c、把属性值放到o4中
o4[key] = value;
}
//3、修改克隆对象,把该对象的name属性改为"李四"
o4.name="coder"
console.log(o4); //最终的目标对象的结果
//。。。后续如果修改了o4对象中的相关属性,就不会影响到o3
</script>
</html>
3.封装拷贝继承函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
</body>
<script>
function extend(source,target){
for (var key in source) {
//key就是o3对象中的每一个属性
//b、获取到对应的属性值
var value = source[key];
//c、把属性值放到o4中
target[key] = value;
}
}
var o3={gender:"男",grade:"初三",group:"第五组",name:"itwangyangcoder"};
var o4={};
extend(o3,o4);
o4.name="coder";
var o5={};
extend(o3,o5);
o5.name="李小龙";
</script>
</html>