JavaScript-继承的多种的方式

来源: 一米八的耗子 发布时间:2019-04-26 15:52:55 阅读量:804

有异议或者理解不对的地方欢迎指出

js继承:通过某种方式让一个对象可以访问到另一个对象中的属性和方法。

 

为什么使用继承:

某些对象会有函数方法,如果把这些函数方法都放置在构造函数内部,会造成浏览器内存的浪费。

 

首先

先定义父类:

定义父类,并在父类的原型上添加方法

 

var p1=new Person();

var p2=new Person();

 

p1.printNamep2.printName.true

p1.printName=p2.printNametrue

如果比较的是对象的话,双等和三等无区别。如果是值的话,双等比较值是否一样,三等还比较两个值在是否指向对一个内存。

 

**结论1**根据上面的比较内容可得知,只要在某个构造函数的prototype属性上添加属性和方法,这个构造函数的属性和方法,都可以被该构造函数的所有实例共享。

 

根据javascript权威指南中的解释,这里的构造函数的prototype对象称之为原型对象

Person.prototypesp1,p2Person构造函数实例)的原型对象

person的原型对象是function.prototype.

 

js的继承方式有哪些

:原型链继承

子类实例的原型等于父类的实例,从而继承父类构造函数的属性.构造函数方法,原型方法,原型属性.

但是原型属性是子类共同使用的.如果修改了,其他子类会受到影响.另外实例无法向构造函数传参.

 

function PersonOne(){

}

PersonOne.prototype= new Person(asd,12);

var personone=new PersonOne(sum1);

personone.proto.proto.sex=123;

console.log(personone.name,personone.age);

console.log(personone.sex);

personone.setAge();

personone.printName();

console.log(personone,"&&&&");

var persontwo=new PersonOne();

console.log(persontwo.name,persontwo.age);

console.log(persontwo.sex)

persontwo.printName();

console.log(persontwo);

输出:

 

想要避免这种情况,可以使用借用构造函数实现,也可以重新new新的子类去继承父类

 

这样除了父类原型属性共享外,构造参数实现了私有化.

 

:借用构造函数实现继承

通过借助call/apply来改变this的指向,从而构造独有的作用域,每个实例继承属性私有化,相互之间不影响.

缺点:构造方法无法复用,每个实例有携带一个构造方法.

function PersonOne(){

Person.call(this,arguments);

}

PersonOne.prototype= new Person();

var personone=new PersonOne(tom,123);

var persontwo=new PersonOne(Jack,456);

console.log(personone);

console.log(persontwo);

console.log(personone.setAge === persontwo.setAge)

console.log(personone.printName === persontwo.printName)

输出:

 

 

:组合继承

把方法放到父类的原型上,实现复用.例如上述的printName方法,唯一不足的是父类构造函数调用两次,子类实例上会覆盖子类原型上的.

 

:原型继承

通过在中间生成对象,使用中间对象去继承父类,最后接收生成的新对象.

f

核心:

(1)function create(obj){

var F = function(){};

F.prototype = obj;

return new F();

}

用法:var person=new Person();

var proto=create(person);

不足:原型引用的属性会被实例共享,而且无法实现复用.

 

:寄生组合继承

相对于来说较为完善.(Es6提供Object.create创造新对象的方法);

function Person(name,age){

this.name=name;

this.age=age;

this.setAge=function(){

console.log(this.age);

}

}

Person.prototype.printName=function(){

console.log(this.name);

}

Person.prototype.sex=1;

function PersonOne(){

Person.call(this,arguments);

}

//继承父类原型上的属性和方法,相比之前create去掉了多余的父类实例的属性

var proto=Object.create(Person.prototype);

//将生成的proto新对象与PersonOne进行关联,相当于PersonOne实例化的实例.

proto.constructor=PersonOne;

//关联原型,实例化后proto具有父类的构造属性,方法,原型的方法,属性

PersonOne.prototype=proto;

 

自己在编写的时候,发现这个问题.

function Person(){

this.name=parent

this.arr=[1,2];

}

Person.prototype.printName=function(){

console.log(this.name);

}

 

 function PersonOne(){

 

 }

 

 PersonOne.prototype=new Person();

 var person=new PersonOne();

 person.name="2";

 person.arr.push(4)

 

 console.log(person)

 

 var per2=new PersonOne();

 

 console.log(per2)

 

name属性在实例上实例化,但是arr却并没有实例化,原因在于arr为引用类型,在赋值的时候实例会随着原型链找到arr的位置并修改值(arr在堆上的地址是唯一的).nameString类型,所以不能直接修改值,需要通过实例化生成对象,从而修改值.每一个实例化的对象在栈上的位置不同,具有私有化.


标签: PHP 环境搭建
分享:
评论:
你还没有登录,请先