Open YvetteLau opened 5 years ago
一楼的对象真好
1.引用类型的方法被所有实例共享,也就是说可以一个方法,写遍天下,哈哈。
1.优点也是缺点,子类实例共享属性,造成实例之间的属性会互相影响。
function Animal() {
this.name = ['cat', 'dog', 'person'];
}
Animal.prototype.getName = function (n) {
return this.name[n];
};
function Dog() {
}
Dog.prototype = new Animal();
let dog1 = new Dog();
console.log(dog1.getName(1));
function Animal() {
function getName() {
return this.name;
}
return {
getName: getName
}
}
let dog = new Animal();
dog.name = 'dog';
console.log(dog.getName());
class Animal {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
class Dog extends Animal {
constructor(name, age, eat) {
super(name, age);
this.eat = eat;
}
showEat() {
alert(this.eat);
}
}
let huang = new Dog('阿黄', 2, '狗粮');
huang.showEat();
function Animal(name,class){
this.name = name
this.class = class
this.protetype.likeName=function(){
console.log(this.name)
}
this.protetype.likeClass=function(){
console.log(this.class)
}
}
function Dog(){
}
Dog.protetype = new Animal()
var dog = new Dog('燕子','鸟类')
dog.likeName()
原型链继承的优缺点? 优点:引用类型的方法被所有实例共享,也就是说一个方法,可以到处使用。 缺点:被所有子类实例共享属性,造成实例之前的属性会相互影响。
function Animal(name){
this.name = name;
}
Animal.prototype.getName=function(){
return this.name
}
function Dog(name,age){
Animal.call( this , name)
this.age = age;
}
Dog.prototype=new Animal()
let dog=new Dog('猫',10);
console.log(dog.getName()+'年龄:'+dog.age)
ECMAScript 中描述了原型链的概念,并将原型链作为实现继承的主要方法。其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。简单回顾一下构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。那么,加入我们让原型对象等于另一个类型的实例,结果会怎么样呢?显然,此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立,如此层层递进,就构成了实例与原型的链条。这就是所谓原型链的基本概念。 --- 《JavaScript 高级程序设计》 6.3.1 原型链
这是从《JavaScript 高级程序设计》中关于原型链的解释,简单说就是构造函数都有一个原型对象,实例包含原定对象的内部指针,如果让原型对象等于实例,就完成了原型链的继承。
// 构造函数
function Animal(name,six){
this.name = name;
this.six = six;
}
Animal.prototype.cry = function(){
return '嘤嘤嘤';
}
使用原型链继承,使原型对象等于实例。
function Dog(name,age){
this.name=name;
this.age = age;
}
Dog.prototype = new Animal('怪兽','未知');
Dog.prototype.run = function(){
return '鸭子类型';
}
// 完成实例化,检测继承
var erHa = new Dog('哈士奇', 5);
console.info(erHa.name); // => 哈士奇
console.info(erHa.six); // => 未知
console.info(erHa.age); // => 5
console.info(erHa.cry()); // => 嘤嘤嘤
console.info(erHa.run()); // => 鸭子类型
在OO语言中,继承方式通常有两种接口继承和实现继承。 在JavaScript中无法实现接口继承(由于函数没有签名),只支持实现继承(通常依靠原型链来实现继承)。
原型链实现继承的基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。
原型链的缺点?
原型链的优点?
- 由以上可知,通过原型链继承的方式,原先存在父类型的实例中的所有属性和方法,现在也能存在于子类型的原型中了。
实现原型链继承
必须基于一个已有对象来实现,即必须有一个对象可以作为另一个对象的基础。
function Animal(o) {
function F(){};
F.prototype = o;
return new F();
}
let dog = {
name: 'origin',
type: 'shiba',
friends: ['KUN', 'Kris'],
intr: function() {
console.log(`${this.name}的朋友有:${this.friends}`);
},
}
let otherDog = Animal(dog);
otherDog.name = '小白';
otherDog.friends.push('小新');
otherDog.intr(); // 小白的朋友有:KUN,Kris,小新
let anotherDog = Animal(dog);
anotherDog.name = '小智';
anotherDog.friends.push('皮卡丘');
anotherDog.intr(); // 小智的朋友有:KUN,Kris,小新,皮卡丘
otherDog.intr(); // 小白的朋友有:KUN,Kris,小新,皮卡丘
dog.intr(); // origin的朋友有:KUN,Kris,小新,皮卡丘
//dog的friends不仅属于dog自己所有,而且也会被otherDog 和 anotherDog 共享。
在没有必要兴师动众地创建构造函数,而只想让一个对象与另一个对象保持类似的情况,原型链继承是完全可以胜任的,不过要记得包含引用值的属性始终都会共享相应的值(就像上面的 friends
和 intr
)。
刚看完书想写,上面老哥直接搬出来就不复述了。
function Developer() {
this.name = "";
this.language = "i user javascript to ";
}
Developer.prototype.sayHello = function() {
return this.name + this.language;
};
function learner() { this.name = "i'm a fontEndApe,"; this.hobby = "write bug"; }
function bigGod() { this.hobby = "repair bug"; }
learner.prototype = new Developer(); bigGod.prototype = new Developer(); let cainiao = new learner(); let yutou = new learner(); console.log(cainiao.sayHello() + cainiao.hobby); console.log(yutou.sayHello() + yutou.hobby); // 子类实例互相影响
eg:
function Animal () {
this.type =['origin']
}
Animal.prototype.tellOrigin = function () {
console.log(this.type)
}
Animal.prototype.setOrigin = function (type) {
this.type.push(type)
}
function Dog () {
this.ownType = 'dog'
}
Dog.prototype = new Animal()
Dog.prototype.tellOwnType = function () {
console.log(this.ownType)
}
const dog1 = new Dog()
dog1.setOrigin('evolve')
const dog = new Dog()
dog.tellOwnType() // 'dog'
dog.tellOrigin() // ['origin', 'evolve']
如上面代码所示:
- 原型链继承
原型链继承的基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。
function Animal(name, age) {
this.name = name;
this.age = age;
}
Animal.prototype.say = function() {
return this.name;
}
function Dog() {
}
//Dog的原型对象是 Animal 的实例
//Dog的原型对象具有 Animal 实例的所有属性和方法,其内部还有一个指针指向Animal的原型
Dog.prototype = new Animal('dog', 2);
Dog.prototype.bark = function() {
console.log('汪汪汪');
}
let Jack = new Dog();
优点:
引用类型的方法被所有实例共享。
缺点:
原型链是实现继承的主要方法,其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。他的优点是可以实现对父级的复用,也正是因为子类间可以共享父类,因此属性间会相互影响。
function Animal(name,age){
This.name = name;
This.age = age;
}
Animal.prototype.sayName = function(){
Return this.name;
}
Function Dog(){
}
Dog.prototype = new Animal(‘yay ’,2);
Dog.protype.sayHi = function(){
Console.log(‘hi’);
}
Var dog = new Dog();
//不会徒手敲代码,几乎是看着楼上小姐姐写完的😩😩
原型链是实现继承的主要方法,其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。他的优点是可以实现对父级的复用,也正是因为子类间可以共享父类,因此属性间会相互影响。 function Animal(name,age){ This.name = name; This.age = age; } Animal.prototype.sayName = function(){ Return this.name; } Function Dog(){ } Dog.prototype = new Animal(‘yay ’,2); Dog.protype.sayHi = function(){ Console.log(‘hi’); } Var dog = new Dog(); //不会徒手敲代码,几乎是看着楼上小姐姐写完的😩😩
继承是重要的基础知识,本周一起巩固~
function Animal(name) {
this.name = name;
}
Animal.prototype.getName = function() {
console.log(this.name)
}
function Dog() {
}
Dog.prototype = new Animal('hashiqi')
let hashiqi= new Dog();
优点:父类方法得到了复用 缺点:属性被所有子类实例共享,修改其中一个子类实例的属性,都会被影响。在创建子类实例的时候,不能向父类构造函数传参。
原型链继承: 利用原型让一个引用类型继承另一个引用类型的属性和方法。实现的本质是利用一个新类型的实例重写原型对象,让当前的类型的实例对象继承这个新类型实例对象上的属性和方法。
缺点
优点
Dog继承Animal
function Animal(species) {
this.species = species;
}
Animal.prototype.getSpecies = function() {
return this.species;
}
function Dog() {
this.species = 'dog';
}
Dog.prototype = new Animal();
Dog.prototype.bark = function() {
console.log('waaaaaaaaa~');
}
let dog = new Dog();
console.log(dog.getSpecies()); // 'dog'
dog.bark(); // 'waaaaaaaaa~'
ECMAScript中描述了原型链的概念,并将原型链作为实现继承的主要方法。 其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。 可以理解为原型对象prototype就是两个引用类型的中间媒介。 有三个重要的概念:构造函数,原型,实例 理解三者的关系对理解原型链至关重要。 每一个构造函数都有一个原型对象 原型对象都包含一个指向构造函数的指针 实例都包含一个指向原型对象的内部指针
function Animal(){
this.type='Animal'
}
Animal.prototype.getType = function(){
return this.type
}
function Dog(){
this.name='拉布拉多'
}
Dog.prototype=new Animal()
Dog.prototype.getName = function(){
return this.name
}
var labuladuo=new Dog()
console.log(labuladuo.getType())
原型链可以用来实现继承,但是也存在一些问题。 最主要就是,包含引用类型值的原型。
function SuperType(){
this.colors=["red","blue","green"]
}
function SubType(){}
SubType.prototype=new SuperType()
var instance1=new SubType()
instance1.colors.push("black")
console.log(instance1.colors)
var instance2=new SubType()
console.log(instance2.colors)
第二个问题,在创建子类型的实例时,不能向超类型的构造函数中传递参数。 没有办法在不影响所有对象实例的情况下,给超类型的构造函数传递参数。
function Animal(name) {
this.info = {
name,
};
}
Animal.prototype.sayName = function() {
console.log(this.info.name);
};
function Cat() {}
Cat.prototype = new Animal('xx');
let cat1 = new `Cat();`
let cat2 = new Cat();
console.log(cat1.info.name, cat2.info.name); // xx xx
cat1.info.name = 'yy'
console.log(cat2.info.name) // yy
缺点:如果存在父类属性是引用类型的,所有子类继承后,会相互影响;在 new 子类的时候,不能向父类传递参数。 优点:可以复用父类的方法
优点:子能继承父的方法和属性,不需要重新写一遍,能增加代码的服用 缺点:子类只能用父类的属性和方法
function Animal(type, name){
this.type = type
this.name = name
}
Animal.prototype.getNameAndType = function () {
console.log(`name: ${this.name} , type: ${this.type}`)
}
function Dog() {
}
Dog.prototype = new Animal('dog', '小黑')
var dog = new Dog()
dog.getNameAndType()
function Animal(){
this.species = '哈士奇'
}
Animal.prototype.getSpecies = function(){
return this.species
}
function Dog(){
this.species = '阿拉斯加犬'; // 在子类改变了父类的属性
}
Dog.prototype = new Animal(); // 继承了Animal的属性和方法
var dog1 = new Dog();
var dog2 = new Dog();
console.log(dog1.getSpecies()); // 阿拉斯加犬
console.log(dog2.getSpecies()); // 阿拉斯加犬,所有实例都被实例改变了
·
原型继承
优点:复用父级方法
缺点:子类没有自己的属性,所有属性方法只能复用父级,处理不好容易跟别的实例串数据
代码如下: