最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 【js】原型链

    正文概述 掘金(Eric很稳)   2021-03-05   474

    js 和 Java、C++ 等传统面向对象的编程语言不同,它是没有类(class,ES6 中的class也只不过是语法糖,并非真正意义上的类)的概念,而在 js 中,一切皆是对象(object)。在基于类的传统面向对象的编程语言中,对象由类实例化而来,实例化的过程中,类的属性和方法会被拷贝到这个对象中;对象的继承实际上是类的继承,在定义子类继承于父类时,子类会将父类的属性和方法拷贝到自身当中。这类语言中,对象创建和继承行为都是通过拷贝完成的。但在 js 中,对象的创建、对象的继承(更好的叫法是对象的代理,因为它并不是传统意义上的继承)是不存在拷贝行为的。因此类、继承这些特点都不属于 js

    prototype 、 __proto__ 以及 constructor

    __proto__constructor是每个对象都有的属性,而prototype是函数对象独有的属性

    __proto__属性指向它们的原型对象(也可以理解为父对象),作用就是当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会去它的__proto__属性所指向的那个对象(父对象)里找,如此反复,直到__proto__属性的值为 null,然后返回 undefined,__proto__的终点是 null。通过__proto__属性将对象连接起来的这条链就是 原型链

    prototype属性指向这个函数的原型对象,也就是这个函数创建的实例对象的原型对象,作用就是让该函数所实例化的对象们都可以找到公用的属性和方法。任何函数在创建的时候,其实会默认同时创建该函数的原型对象

    constructor属性指向该对象的构造函数,每个对象都有构造函数(本身拥有或继承而来),Function对象比较特殊,它的构造函数就是自己,所以constructor属性的终点就是Function函数

    function People(){
        ...
    }
    var people = new People();
    console.log(people.__proto__ === People.prototype)//true
    console.log(people.constructor === People.prototype.constructor)//true
    

    关系图如下:

    graph LR
    prototype(原型对象)
    constructorFunc(构造函数)
    object(实例对象)
    constructorFunc --new--> object
    constructorFunc --prototype--> prototype
    prototype --constructor--> constructorFunc
    object -.constructor.-> constructorFunc
    object --__proto__--> prototype
    

    js 实现类

    在 ES6 之前 js 还没有 class 关键字,可以使用一下几种方式模拟声明类:

    1、工厂模式

    function createPerson(name){
        var person = new Object();
        person.name = name;
        return person;
    }
    var person = createPerson('Leo')
    

    2、构造函数法:

    function Person(name){
        this.name = name;//this 代表新创建的实例对象
    }
    var person = new Person('Leo')
    

    在 ES6 新增 class 关键字声明类(其实只是语法糖):

    class People{
        name = 'default';
        constructor(name){
            this.name = name;
        }
    }
    

    js 实现继承

    背景

    js 是由 Brendan Eich 负责开发的,当时面向对象很兴盛,Brendan Eich 无疑也受到了影响,js 中一切皆为对象,所以必须有一种机制,将所有对象联系起来。但是,Brendan Eich 没引入"类"的概念,因为一旦有了"类",js 就是一种完整的面向对象编程语言了,过于正式了。想到 C++ 和 Java 使用 new 命令时,都会调用"类"的构造函数 constructor。他就做了一个简化的设计,在 js 中,new 命令后面跟的不是类,而是构造函数

    构造函数继承

    说明:直接利用 call 或者 apply 方法将父类构造函数的 this 绑定为子类构造函数的 this 就可以

    缺点:无法继承父类原型链上的属性与方法

    function Parent(){
        this.name = "parent's name"
    }
    Parent.prototype.say = function(){
    	console.log(this.name)
    }
    function Child(){
      Parent.call(this)  //构造函数继承核心代码
    }
    let child = new Child()
    console.log(child.name) // parent
    console.log(child.say()) // child.say is not a function
    
    原型继承

    说明:将子类的原型挂载到父类上

    缺点:子类 new 出来的实例,父类的属性没有隔离,会相互影响

    function Parent() {
      this.arr = [1, 2, 3]
    }
    function Child() {
    }
    Child.prototype = new Parent() //原型继承核心代码
    let child1 = new Child()
    let child2 = new Child()
    child1.arr.push(4)
    console.log(child1.arr, child2.arr) // [1, 2, 3, 4]  [1, 2, 3, 4]
    
    组合继承

    说明:组合上面的构造函数与原型继承的功能

    缺点:call() 方法已经拿到父类所有的属性 ,后面再使用原型时也会有父类所有属性

    function Parent() {
      this.name = 'parent'
    }
    Parent.prototype.say = function () {
    	console.log(this.name)
    }
    function Child() {
      Parent.call(this)
    }
    Child.prototype = new Parent()
    let child = new Child();
    
    child:
    	Child {name: "parent"}
    	name: "parent"
        __proto__: Parent
            name: "parent" // 重复的属性
            __proto__:
                say: ƒ ()
                constructor: ƒ Parent()
                __proto__: Object
    
    寄生式组合继承

    说明:解决组合继承重复属性的问题,直接将子类的原型等于父类的原型,或者是用 Object.create 继承原型但不执行父类构造函数(目前最完美的继承实现方式)

    function Parent() {
      this.name = 'parent'
    }
    Parent.prototype.say = function () {
    	console.log(this.name)
    }
    function Child() {
      Parent.call(this)
      this.type = 'child'
    }
    Child.prototype = Parent.prototype
    Child.prototype.constructor = Child
    //修复重写子类原型导致子类constructor属性被修改
    
    Class 继承

    说明:ES6 新增,class 是一个语法糖,基于寄生组合继承来实现

    class Parent{
    	constructor(){
            this.name = 'parent'
            this.arr = [1, 2, 3]
        }
        say(){
      	    console.log(this.name)
        }
    }
    class Child extends Parent{
        constructor(){
            super() // 通过 super() 调用父类构造函数
        }
    }
    

    起源地下载网 » 【js】原型链

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元