一、修改子类原型对象的引用属性,其父类的原型对象的引用属性跟着改变
二、欢迎你们来指正!javascript
a) 实现方式:遍历字面量2赋值给字面量1java
b) 注意点:必须用[]语法,不能用点语法app
c) 缺点:修改字面量1会对字面量2形成影响函数
# 继承的实现(混入式继承) <script> var dog = { name: "啦啦小新", age: 20, friends: ["哗啦哗啦", "哔哩哔哩"] } //dog1 var dog1 = {}; //dog1 可以拥有dog对象中全部的属性和方法 //遍历dog对象,拷贝它全部的属性和方法设置到本身的身上 for (var k in dog) { //使用[]语法 dog1[k] = dog[k]; } console.log(dog1); //问题:修改其中的某个对象dog1,会对原对象产生影响 //为何:引用类型的赋值(地址) dog1.friends.push("乌拉乌拉"); 哗啦哗啦", "哔哩哔哩","乌拉乌拉"]} console.log(dog); //{name: "啦啦小新",age: 20,friends: ["哗啦哗啦", "哔哩哔哩","乌拉乌拉"]} </script>
a)实现方式:
i.设置构造函数的原型对象的属性和方法(点语法),构造函数建立出来的对象自动共享原型对象中的属性和方法
ii.设置构造函数的原型对象的属性和方法(字面量法),构造函数建立出来的对象自动共享原型对象中的属性和方法
iii.设置子对象的原型对象为父对象的原型对象,再修正构造器,子对象构造函数建立出来的对象自动共享父对象的原型对象中的属性和方法
b)注意点:使用原型替换的方式实现继承的时候,原有原型对象中的属性和方法会丢失
c)缺点:
i.修改一个对象的属性和方法,会影响其余的对象
ii.只能继承原型属性和方法,没法继承实例属性和方法测试
# 原型式继承A <script> function Animal() {} //设置原型对象 Animal.prototype.run = function() { console.log("run"); } Animal.prototype.type = "猫科动物"; //建立对象 //性质:构造函数建立出来的全部对象都自动拥有其对于原型对象上面的全部属性和方法 var a = new Animal(); console.log(a.type); a.run(); </script>
# 原型式继承B <script> var obj = { name: "默认的名字", age: 20 }; function Animal() {} //设置原型对象 Animal.prototype = obj; //修正构造器属性 Animal.prototype.constructor = Animal; //建立对象 //性质:构造函数建立出来的全部对象都自动拥有其对于原型对象上面的全部属性和方法 var a = new Animal(); console.log(a.name); console.log(a.age); </script>
# 原型式继承C <script> function Animal() {} //设置原型对象 Animal.prototype.run = function() { console.log("run"); } function Dog() {} //设置原型 Dog.prototype = Animal.prototype; //建立对象 var dog = new Dog(); dog.run(); //问题: //001 Dog 的原型对象和Animal的原型对象是同一个,不管是谁修改了原型对象会影响到另一个 //002 只能继承Animal的原型属性和方法,没法获得其实例属性和方法 </script>
a)实现方式:
i.设置子对象的原型对象为 new 父对象构造函数
ii.子对象构造函数建立出来的对象自动共享父对象中的属性和方法(实例和原型属性和方法);
b)注意点:
i.设置原型链继承必须在设置子对象的属性和方法以前
ii.若是设置同名的实例属性或方法,会覆盖父对象中的属性和方法
iii.设置原型链继承以后,须要修正构造器属性指向
iv.完成继承后再以字面量的方式设置子对象原型,会断开继承
c)缺点:
i.修改一个对象的属性和方法,会影响其余的对象
ii.没法对父对象进行传参优化
# 构造函数A - B <script> //01 提供两个构造函数 //02 设置A构造函数的原型对象的属性和方法 //03 设置原型链继承 //04 建立B类型的对象 使用B构造函数来建立对象 function A() { this.description = "描述信息"; this.logDes = function() { console.log(this.description); } } A.prototype.name = "A的默认名称"; A.prototype.showName = function() { console.log(this.name); } function B() {}; B.prototype = new A(); //完成继承 B.prototype.constructor = B; //修正构造器 var b1 = new B(); console.log(b1.name); //A的默认名称 b1.showName(); //A的默认名称 b1.logDes(); //描述信息 </script>
a)实现方式:
i.子对象构造函数中设置:父对象构造函数.call/apply(this,参数);
ii.子对象构造函数建立出来的对象自动共享父对象中的实例属性和方法(实例属性和方法);
b)注意点:call和apply方法会改变this的指向,谁调用就指向谁
c)缺点:只能继承实例属性和方法,没法继承原型属性和方法this
<script> //01 提供父类型的构造函数 function SuperType(name) { //02 在构造函数中中设置实例属性,该属性为引用类型 this.family = ['哥哥', '姐姐', '爸爸', '妈妈']; //实例属性 this.name = name; }; //03 提供子类型的构造函数 function SubType() { //经典继承|借用构造函数|伪造对象继承 //SuperType.call(this); //构造参数传递参数 SuperType.call(this, '张老汉'); }; //04 建立父类型的实例对象,并对内部的实例化属性进行修改 var subDemo1 = new SubType(); var subDemo2 = new SubType(); console.log(subDemo1); alert(subDemo1.family); //哥哥,姐姐,爸爸,妈妈 alert(subDemo2.family); //哥哥,姐姐,爸爸,妈妈 subDemo1.family.push('爷爷', '奶奶'); alert(subDemo1.family); //哥哥,姐姐,爸爸,妈妈,爷爷,奶奶 alert(subDemo2.family); //哥哥,姐姐,爸爸,妈妈 //测试构造函数传递参数 alert(subDemo1.name); </script>
a)实现方式:
i.子对象构造函数中设置:父对象构造函数.call/apply(this,参数);
ii.设置子对象的原型对象为父对象的原型对象;
iii.修正子对象的构造器;
iv.子对象构造函数建立出来的对象自动共享父对象中的属性和方法(实例和原型属性和方法);
b)注意点:call和apply方法是伪继承 /没有继承关系 只是把Person构造函数的属性和方法深复制一份(包括引用类型:指针和堆空间的数据)
c)缺点:修改子类原型方法和原型引用属性,父类原型方法和原型引用属性也跟着变prototype
<script> /*该继承缺点:修改子类原型的方法,父类原型方法也跟着变,其*/ function Person(name) { this.name = name; } Person.prototype.age = 12; Person.prototype.arr = [1,2,3]; Person.prototype.play = function() { console.log(this.name + "playfooterball"); } function Student(name) { Person.call(this, name); /*伪继承 没有继承关系 只是把Person构造函数的属性和方法深复制一份(包括引用类型:指针和堆空间的数据)*/ } Student.prototype = Person.prototype; Student.constructor = Student; Student.prototype.play = function() { console.log(this.name + "playbasketball"); } var s1 = new Student("漳卅"); s1.arr.push(4); console.log(s1); //Student对象 console.log(s1.age); //12 console.log(s1.arr); s1.play(); // 漳卅playbasketball var p = new Person("郭嘉"); p.play(); // 郭嘉playbasketball console.log(p.arr); </script>
a)实现方法:
i.只需把组合继承中的设置子对象的原型对象为父对象的原型对象这一句;
ii.修改成子对象的原型对象为object.create(父对象的原型对象);就OK了指针
<script> function Person(name) { this.name = name; } Person.prototype.age = 12; Person.prototype.play = function () { console.log(this.name + "playfooterball"); } Person.prototype.arr = [1,2,3]; function Student(name) { Person.call(this,name); /*伪继承 没有继承关系 只是把Person构造函数的属性和方法深复制一份(包括引用 类型:指针和堆空间的数据)*/ } Student.prototype = Object.create(Person.prototype); Student.constructor = Student; Student.prototype.play = function(){ console.log(this.name + "playbasketball"); } var s1 = new Student("漳卅"); s1.arr.push(4); console.log(s1);//漳卅 console.log(s1.age);//12 Console.log(s1.arr);//[1,2,3,4] s1.play();//漳卅 playbasketball var p = new Person("郭嘉"); p.play();//郭嘉 playfooterball console.log(p.arr);//[1,2,3,4] </script>
上述代码:修改子类的原型引用类属性,其父类的原型引用类属性跟着改变!code