ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

继承

2022-06-15 21:37:28  阅读:170  来源: 互联网

标签:构造函数 console log Fn1 继承 prototype name


1.继承

继承分为:接口继承,实现继承,在js中只要实现继承,实现继承主要依靠原型链来做到的。

定义:利用原型链让一个对象拥有另一个对象的属性和方法。

让一个构造函数的原型对象等于另一个构造函数的实例

function Fn1(){ this.num=100; } Fn1.prototype.getNum=function(){ console.log(this.num) }; var fn1=new Fn1();
function Fn2(){}; Fn2.prototype=new Fn1(); var fn2=new Fn2();
console.log(fn2.getNum()) //100 console.log(fn2.__proto__) //Fn1 {num: 100} console.log(fn1.__proto__) //{getNum: ƒ, constructor: ƒ} console.log(Fn1.prototype) //{getNum: ƒ, constructor: ƒ}
console.log(Fn1.prototype==fn1.__proto__) //true
console.log(Fn2.prototype.__proto__==fn1.__proto__) //true console.log(fn1.__proto__==Fn1.prototype) //true
console.log(Fn2.prototype.__proto__==Fn1.prototype) //true
1.每个构造函数都有一个原型对象(prototype) 2.每个原型对象都包含一个指向该构造函数的constructor属性 3.每个new出来的实例都包含一个指向原型对象的隐式原型(__proto__)属性

2.构造函数的进阶应用

  •  为什么我们要在构造函数里面定义属性,在构造函数的原型对象上写方法。
  1. 从实例化的过程来看,每个实例化对象的属性大多情况下都是不同的,所有大多数属性是可变的,定义在构造函数里面的属性优先级较高,所以实例化对象可以快速访问使用构造函数中的属性。
  2. 可以通过实例对象来访问保存在构造函数原型对象上的值,但是不能通过实例对象来重写原型上的值,如果一个实例对象修改了一个原型上的属性,其他实例对象在去访问这个实例属性的时候,这个实例属性就不是以前的实例属性了。
  3. 方法大多数情况下都是固定的,因此不必每次实例化的时候都把所有的方法实例化复制一遍。
  4. 构造函数的继承是依托于原型链来完成的,而在原型链中,构造函数的原型对象大多数情况下都是用来共享方法的,当然也可以共享一些衡邵改变的共享共用属性。
  5. 每次实例化都可以得到一个构造函数实例属性的副本,同时又可以共享着共用的方法,这样可以最大限度的节省内存。同时构造函数中的属性也支持床底参数来动态修改
function Fn1(name){
    this.name=name;
    //this.getName=function(){}   //可以这样写--但不建议--原因3
}
//Fn1.prototype.name='1111';  //可以这样写--但不建议--原因2
Fn1.prototype.getName=function(){
    console.log(this.name)
}

var fn1=new Fn1('2222').getName();  //2222
var fn2=new Fn1('3333').getName();  //3333

构造函数与原型组合使用的方式,在js组件化开发过程中是最通用用到的组件化开发方式

3.继承的方式

  •  new实例化的过程
  1. 创建一个空对象,
  2. 把实例对象的隐式原型__proto__指向构造函数的原型prototype(实例对象拥有了构造函数prototype原型对象上的属性和方法)
  3. 把构造函数的this指向替换成实例对象,再执行构造函数,(实例对象拥有了构造函数的属性和方法)
  • 继承的方式
  1. 借用构造函数

      原理:子类型构造函数的内部调用父类型构造函数

    优点:1.子类可以继承父类构造函数中的属性  2.可以给父类构造函数中传递参数

    缺点:子类没办法继承父类构造函数原型上的方法

function Fn1(name){
    this.name=name;
    this.num=100;
}
Fn1.prototype.getName=function(){
    return this.name
}
function Fn2(name){
    Fn1.call(this,name);
    this.job='work'
}

var fn2=new Fn2('name');
console.log(fn2)   //Fn2 {name: "name", num: 100, job: "work"}

   2.组合继承

    原理:利用原型链实现对原型属性和方法的继承,同时通过借用构造函数来实现子类对父类构造函数内部属性的继承(先用借用构造函数的形式让子类继承父类构造函数的属性,再用原型链让子类继承父类原型对象的方法)

    优点:子类可以继承父类构造函数原型上的方法

    缺点:1.会调用2次父类构造函数(一次构建子类原型对象,一次子类构造函数内部构建子类属性)

function Fn1(name){
    this.name=name;
    this.num=100
}
Fn1.prototype.getName=function(){
   console.log(this.name)
}
function Fn2(name){
    Fn1.call(this,name)    //借用构造函数继承属性
    this.job='work'
}
Fn2.prototype=new Fn1();   //使用原型链继承方法
Fn2.prototype.constructor=Fn2;   //非必写--为了修正子类原型对象的constructor的属性
Fn2.prototype.getName=function(){
  console.log(this.name+'-22')
} var fn2=new Fn2('name2'); fn2.getName(); //name2-22 console.log(fn2) //Fn2 {name: "name2", num: 100, job: "work"}

//console.log(fn2 instanceof Fn2) //true
//console.log(fn2 instanceof Fn1) //true
//console.log(fn2 instanceof Array) //false
//console.log(fn2 instanceof Object) //true

//console.log(Fn2.prototype.isPrototypeOf(fn2)) //true
//console.log(Fn1.prototype.isPrototypeOf(fn2)) //true
//console.log(Array.prototype.isPrototypeOf(fn2)) //false
//console.log(Object.prototype.isPrototypeOf(fn2)) //true
//console.log(Object.isPrototypeOf(fn2)) //false

  3.原型式继承(浅拷贝)

    场景:让一个对象与另一个对象保持类似结构。    

    原理:借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型

    优点:构造函数内部和原型上的属性和方法都可以继承

    缺点:包含引用类型值的属性会共享相应的引用类型的值。

 

var obj1={
    name:'name1',
    num:[100,200],
}
//var obj2=obj1;
//console.log(obj2)   //{name: "name1", num: 100}

var obj2=Object.create(obj1);
obj2.name='name2';
obj2.num.push(300)
//console.log(obj2.name);  //name2
//console.log(obj2.num);   //[100, 200, 300]
//console.log(obj1.name); //name2
//console.log(obj1.num);   //[100, 200, 300]

var obj3=Object.create(obj1);
obj3.name='name3';
obj3.num.push(400)
console.log(obj3.name);   //name3
console.log(obj3.num);   //[100, 200, 300, 400]
console.log(obj2.name);  //name2
console.log(obj2.num);  //[100, 200, 300, 400]
console.log(obj1.name);   //name1
console.log(obj1.num);   //[100, 200, 300, 400]

 

  4.寄生式继承

    原理:定义一个独立的函数,在这个函数内部以某种方式来增强参数对象,在增加对象之后再返回对象

var obj1={
    name:'name1',
    num:100,
}
function hanceObj(obj){
    var newObj=Object.create(obj);
    newObj.setObj=function(){
        console.log('23234')
    }
    return newObj;
}
var obj2=hanceObj(obj1);
console.log(obj2) 
 //{setObj: ƒ} { __proto__:{name: "name1" num: 100}}

  5.寄生组合继承

    原理:让第三方构造函数来寄生父类的原型,在子类构造函数内部使用父类.call(子类的实例)改变父类的构造函数的this指向

    优点:1.解决组合继承调用2次父类构造函数的问题  2.节约内存开销

function Fn1(name){
    this.name=name
}
Fn1.prototype.getName=function(){
    console.log(this.name)
}

function Fn2(name){
    Fn1.call(this,name);
}

hanceObj(Fn2,Fn1);

function hanceObj(f2,f1){
    var prototype=Object.create(f1.prototype);
    prototype.constructor=f2
    f2.prototype=prototype;
}

var fn2=new Fn2('name222');
fn2.getName()    //name222

 

标签:构造函数,console,log,Fn1,继承,prototype,name
来源: https://www.cnblogs.com/susu2020/p/16372339.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有