• 原型与继承与class


    对象有属性(专业点叫静态属性)和方法(专业点叫静态方法)和原型属性和原型方法

    image.png

    除了系统自带的那么几百万个对象,我们自己写在js的创建的对象,自定义的对象,都来自对象的构造函数,用来构造对象的函数,叫做构造函数,es6的class也是构造函数,就是一个语法糖而已,还是个残缺的语法糖

    // 写一个完整的构造函数
    // 构造函数的name一般首字母大写,为了好认
    function User(name){
       // 静态属性
       this.name = name;
       // 静态方法
       this.say = function(){ ... }
    }
    // 原型对象
    User.prototype = {
       //原型属性
       prototypeName: "proName",
       //原型方法
       prototypeSay: function(){ ... }
    }
    // 构造函数的私有属性
    User.aa = "aa"
    // 构造函数的私有方法
    User.bb= function(){ ... }
    
    class User{
      constructor(name) {
        //原型属性
        this.name = name;
        //原型方法
        this.say = function(){ ... }
      }
      //原型方法,没有原型属性
      prototypeSay(){ ... },
      // 构造函数的私有属性
      static aa = "aa"
      // 构造函数的私有方法
      static bb = function(){ ... }
    }
    

    构造函数是为了能够大批量的生产方法属性一样,只有某几个通过传参不同而构造属性不同的对象而诞生的工厂,并且可以通过继承使方法被无限传递或者重写才是构造函数的精髓

    原生的继承方式有六种

    image.png

    但最前面的五个各有缺陷,直接上完美方式的代码,寄生组合继承
    其他几种自己搜,不混淆

    // 父函数SuperType
    function SuperType(country) {
      this.country = country; 
      this.sayCountry = function() {
         console.log(this.country);
      }
    }
    // 父函数SuperType的原型方法
    SuperType.prototype.proSay = function() {
      console.log(this.country);
    }
    // 子函数SuperType
    function SubType(country,age) {
      SuperType.call(this,country);
      this.age = age;
    }
    // 核心代码,继承
    function inheritPrototype(subType,SuperType) {
      var prototype = Object(SuperType); // 创建对象
      prototype.constructor = subType; // 增强对象
      subType.prototype = prototype; // 指定对象
    }
    // 继承方法执行,参数是(子,父) 
    inheritPrototype(SubType,SuperType); 
    
    // 继承完成后
    // 子函数添加原型对象
    SubType.prototype.sayAge = function() {   
      console.log(this.age);
    }
    var a = new SuperType("中国")
    var b = new SubType("中华",18)
    

    class语法糖

    class SuperType{
      constructor(country) {
        this.country = country;
        this.sayCountry = function(){}
      }
      proSay(){  },
    }
    
    class SubType extend SuperType{
      constructor(age) {
        super();
        this.age = age;
      }
      sayAge(){  },
    }
    var a = new SuperType("中国")
    var b = new SubType("中华",18)
    

    继承的成功就是在于,子函数有父函数的方法,父函数没有子函数的新方法
    上面两个写法打印出来如下图,都符合继承的要求

    image.png

    原型链的走向
    先上个图,图上没有关于继承的答案,这个图能看一年

    image.png

    分析过程就不说了,需要自己理解,说说几个理论
    一个对象的__proto__属性等于对象的构造函数的prototype对象
    上面说的这个属性/对象,他的constructor属性又指向构造函数本事
    所有function的__proto__都指向Function的prototype,包括Function自己,这是个环

    一个面试题
    问:
    C构造函数继承于构造函数B,B构造函数继承于构造函数A,问C的原型链怎么走到null
    答案:
    继承者的prototype的prototype的prototype...直到prototype为underfind时说明到了function原型的终点,也就是到了Object层,这时取出__proto__(这个__proto__也就是Object的prototype),再取一层__proto__就是null(尽头)

    先有鸡先有蛋
    这是个新有函数还是先有对象的问题,函数是对象,对象通过函数new出来,这是个相互嵌套的关系,但是程序肯定是有一个终点的,那到底是先有鸡还是先有蛋

    我找到了两个答案
    答案一
    先有的Object.prototype, Object.prototype构造出Function.prototype,然后Function.prototype构造出Object和Function。
    Object.prototype是鸡,Object和Function都是蛋。

    答案二
    函数function就是对象,所有的函数是被Function这个函数对象构造出来的。Function是最顶层的构造器。它构造了系统中所有的对象,包括用户自定义对象,系统内置对象,甚至包括它自已。这也表明Function具有自举性(自已构造自己的能力)。这也间接决定了Function的call和constructor逻辑相同。每个对象都有一个 constructor 属性,用于指向创建其的函数对象。

    我更相信第二个答案

    new的原理,模拟一个new

    function new(func) {
       let target = new Object();
       target.__proto__ = func.prototype;
       let res = func.call(target);
       if (res && typeof(res) == "object" || typeof(res) == "function") {
    	return res;
       }
       return target;
    }
    
  • 相关阅读:
    制作A4纸打印的网页像素大小设置(转)
    关于Vue.use()详解
    Vue的axios如何全局注册
    JS中的apply,call,bind深入理解
    JS异步编程 (2)
    JS异步编程 (1)
    彻底搞清楚javascript中的require、import和export(js模块加载规范的前世今生)
    IPv6地址分类及表示方法
    SublimeText3追踪函数工具CTags设置及使用
    转-编写CGI小结
  • 原文地址:https://www.cnblogs.com/pengdt/p/12037973.html
Copyright © 2020-2023  润新知