css哪些属性可以继承-前端JavaScript的6种继承方式及其优缺点总结

来源|

第一种:原型链继承

利用原型链的特性进行继承

function Parent(){
    this.name = 'web前端';
    this.type = ['JS','HTML','CSS'];
}
Parent.prototype.Say=function(){
    console.log(this.name);
}
function Son(){};
Son.prototype = new Parent();
son1 = new Son();
son1.Say();

上面例子的解释:

①创建一个名为Parent的构造函数,暂且称为父构造函数,它有两个属性name、type

②通过Parent构造函数(即原型对象)的属性设置Say方法。 此时Parent有2个属性和1个方法

③创建一个名为Son的构造函数,暂且称之为子构造函数

④ 设置Son的属性(即原型对象)为父构造函数Parent的实例对象,即子构造函数Son继承父构造函数Parent。 此时Son也有2个属性和1个方法

实例化Son构造函数,并将结果参数赋予变量son1,即son1是实例化对象,它也有2个属性和1个方法

⑥ 输出son1的Say方法,结果为“web backend”

优点:可以实现继承

缺点:

①因为Son.prototype(即原型对象)继承了Parent实例化对象,这就导致所有Son实例化对象都是一样的,它们都共享原型对象的属性和技能。 代码如下所示:

son1 = new Son();
son2 = new Son();
son1.type.push('VUE');
console.log(son1.type);//['JS','HTML','CSS','VUE']
console.log(son2.type);//['JS','HTML','CSS','VUE']

结果son1和son2都是['JS', 'HTML', 'CSS', 'VUE']

②子构造函数实例化对象,传递参数比较困难

第二种:构造函数继承

通过构造函数调用方法继承,直接看代码:

function Parent(){
    this.name = 'web前端';
    this.type = ['JS','HTML','CSS'];
}
function Son(){
    Parent.call(this);
}
son1 = new Son();
son1.type.push('VUE');
console.log(son1.type);//['JS','HTML','CSS','VUE']
son2 = new Son();
console.log(son2.type);//['JS','HTML','CSS']

上面例子的解释:

①创建父构造函数Parent,它有两个属性:name和type

②创建子构造函数Son,并通过函数内部的call方法调用父构造函数Parent,实现继承

③分别创建构造函数Son的两个实例化对象son1和son2,向son1的type属性添加元素,但son2没有添加新元素,结果不同,说明已经实现了独立性

优势:

① 实现实例化对象的独立性;

② 还可以给实例化的对象添加参数

function Parent(name){
    this.name = name;
}
function Son(name){
    Parent.call(this,name);
}
son1 = new Son('JS');
console.log(son1);//JS
son2 = new Son('HTML');
console.log(son2);//HTML

缺点:

①方法全部定义在构造函数中,每次实例化对象都要重新创建,基本上很难实现函数复用

②call方法只调用父构造函数的属性和技巧css哪些属性可以继承,没有办法调用父构造函数的原型对象

第三种:组合继承

利用原型链继承和构造函数继承各自的优点结合使用,还是看代码:

function Parent(name){
    this.name = name;
    this.type = ['JS','HTML','CSS'];
}
Parent.prototype.Say=function(){
    console.log(this.name);
}
function Son(name){
    Parent.call(this,name);
}
Son.prototype = new Parent();
son1 = new Son('张三');
son2 = new Son('李四');
son1.type.push('VUE');
son2.type.push('PHP');
console.log(son1.type);//['JS','HTML','CSS','VUE']
console.log(son2.type);//['JS','HTML','CSS','PHP']
son1.Say();//张三
son2.Say();//李四

上面例子的解释:

①创建一个名为Parent的构造函数,它有两个属性name和type

②通过Parent构造函数(即原型对象)的属性设置Say方法。 此时Parent有2个属性和1个方法

③创建子构造函数Son,并通过函数内部的call方法调用父构造函数Parent,实现继承

④子构造函数Son继承了父构造函数Parent,Son也有2个属性和1个方法

⑤分别创建构造函数Son的两个实例化对象son1和son2,传递不同的参数,在type属性中添加不同的元素,调用原型对象Say方法

优势:

① 使用原型链继承来实现原型对象的继承

② 使用构造函数继承来实现属性的继承,参数可以是

组合功能基本满足JS的继承,比较常用

缺点:

在任何一种情况下,父构造函数都会被调用两次:一次是在创建子构造函数的原型时,一次是在子构造函数内部

第四种:原型继承

创建一个将参数作为对象原型对象的函数

function fun(obj) {
    function Son(){};
    Son.prototype = obj;
    return new Son();
}
var parent = {
    name:'张三'
}
var son1 = fun(parent);
var son2 = fun(parent);
console.log(son1.name);//张三
console.log(son2.name);//张三

上面例子的解释:

①创建函数fun,内部定义一个构造函数Son

②设置Son的原型对象为参数,参数为对象,完成继承

③Son实例化并返回,即返回一个实例化的对象

css哪些属性可以继承_css继承父级样式_问道天书继承暗属性可以继承么

优缺点:与原型链类似

第五种:寄生遗传

在原型继承的基础上,丰富函数内部的对象

function fun(obj) {
    function Son() { };
    Son.prototype = obj;
    return new Son();
}
function JiSheng(obj) {
    var clone = fun(obj);
    clone.Say = function () {
        console.log('我是新增的方法');
    }
    return clone;
}
var parent = {
    name: '张三'
}
var parent1 = JiSheng(parent);
var parent2 = JiSheng(parent);
console.log(parent2.Say==parent1.Say);// false

上面例子的解释:

① 在原型继承的基础上封装一个吉生函数

② 改进fun函数返回的对象,添加Say方法,最后返回

③调用JiSheng函数两次,分别将参数赋予变量parent1和parent2

④比较parent1和parent2,结果为假,实现独立

优缺点:与构造函数继承类似css哪些属性可以继承,调用函数需要重新创建,无法实现函数复用,效率较低

这里补充一个知识点,ES5新增了一个方法Object.create(),相当于封装了原型继承。 该方法可以接收两个参数:第一个是新对象的原型对象(可选),第二个是新对象的新属性,所以前面的代码也可以是这样的:

function JiSheng(obj) {
    var clone = Object.create(obj);
    clone.Say = function () {
        console.log('我是新增的方法');
    }
    return clone;
}
var parent = {
    name: '张三'
}
var parent1 = JiSheng(parent);
var parent2 = JiSheng(parent);
console.log(parent2.Say==parent1.Say);// false

问道天书继承暗属性可以继承么_css继承父级样式_css哪些属性可以继承

第六类:寄生组合继承

利用组合继承和寄生继承

关于组合继承方式我们已经说过了,它的缺点是父构造函数被调用了两次,一次是在创建子原型时,另一次是在子构造函数内部,那么我们只需要优化这个问题即可。 ,即减少对父构造函数的一次调用,只需利用寄生继承的特性继承父构造函数的原型来创建子原型即可。

function JiSheng(son,parent) {
    var clone = Object.create(parent.prototype);//创建对象
    son.prototype = clone;      //指定对象
    clone.constructor = son;     //增强对象
}
function Parent(name){
    this.name = name;
    this.type = ['JS','HTML','CSS'];
}
Parent.prototype.Say=function(){
    console.log(this.name);
}
function Son(name){
    Parent.call(this,name);
}
JiSheng(Son,Parent);
son1 = new Son('张三');
son2 = new Son('李四');
son1.type.push('VUE');
son2.type.push('PHP');
console.log(son1.type);//['JS','HTML','CSS','VUE']
console.log(son2.type);//['JS','HTML','CSS','PHP']
son1.Say();//张三
son2.Say();//李四

上面例子的解释:

① 封装一个函数 JiSheng,有两个参数,参数1为子构造函数,参数2为父构造函数

② 使用Object.create()克隆父构造函数的原型作为克隆

③ 使用副本作为子构造函数的原型

④在副本中添加构造函数属性,因为更改③中的原型会导致副本失去默认属性

的优点和缺点:

目前JS继承中采用了组合继承和寄生继承的优点。

总结

为了更好地理解JS继承方法,你必须了解构造函数、原型对象、实例化对象、原型链等概念。

我是@半糖学入头,专注于后端技术领域的分享,一名后端从业者,关注我,跟我一起学习,共同进步!