zoukankan      html  css  js  c++  java
  • javaScript系列 [33] new

    本文介绍JavaScript 语言中 new 关键字调用构造函数的内部执行细节和模拟实现。

    在 JavaScript 语言中,我们通过 new 关键字来调用构造函数以创建实例对象,或者是通过 new关键字来调用类以实例化,class是ES6新增的特性,可以理解为它和构造函数是一样的。

    在下面的代码中,我们先提供了构造函数Person,然后设置原型对象并创建了实例对象 p。

    /* 01-提供构造函数 */
    function Person(name, age) {
        this.age = age;
        this.name = name;
        this.showName = function() {
            console.log("姓名:" + this.name);
        }
        this.showAge = function() {
            console.log("年龄:" + this.age);
        }
    }
    
    /* 02-设置原型对象 */
    Person.prototype.showInfo = function() {
        this.showName();
        this.showAge();
    }
    
    /* 03-创建实例对象 */
    let p = new Person("Yong", 16);
    
    /* 04-测试代码 */
    console.log(p);
    p.showInfo();
    
    /*  打印输出结果:
    Person {
      age: 16,
      name: 'Yong',
      showName: [Function],
      showAge: [Function] 
    }
    姓名:Yong
    年龄:16
    */
    

    构造函数的代码如果换成是Class,那结果也是一样的。这里我们需要关注下当使用 new 关键字 来调用构造函数或者类的时候都做了些什么,也就是内部的实现细节,下面通过代码注释的方式来对这些细节进行说明。

    /* 01-提供构造函数 */
    function Person(name, age) {
        /* [1] 创建空对象 */
        /* 模拟:let o = {} */
    
        /* [2] 设置原型对象访问 */
        /* 模拟:o.__proto__ = Person.prototype; */
    
        /* [3] 修改 this 指向空对象 */
        /* 模拟:this = o */
    
        /* [4] 通过 this 来设置实例属性 */
        this.age = age;
        this.name = name;
    
        /* [5] 通过 this 来设置实例方法 */
        this.showName = function() {
            console.log("姓名:" + this.name);
        }
        this.showAge = function() {
            console.log("年龄:" + this.age);
        }
    
        /* [6] 默认总是返回内部新创建的对象(this) */
        /* 如果主动 return , 若跟的是引用类型则直接返回,值类型则忽略 */
        /* 模拟:return this */
    }
    
    /* 02-设置原型对象 */
    Person.prototype.showInfo = function() {
        this.showName();
        this.showAge();
    }
    
    /* 03-创建实例对象 */
    let p = new Person("Yong", 16);
    

    最后,再花点时间来封装个函数以模拟new 关键字的功能,列出给定代码和测试数据。

    /* 01-模拟 new 关键字 */
    function mockNew() {
        /* [1]-获取构造器 */
        /* 说明:arguments类数组执行删除操作,接收删除后的元素 */
        let Constructor = [].shift.call(arguments);
    
        /* [2]-创建空对象 */
        let o = {};
    
        /* [3]-设置新对象的原型指向构造函数的原型对象 */
        /* 注意:默认 o.__proto__ 指向的是 Object.prototype */
        o.__proto__ = Constructor.prototype;
    
        /* [4] 把剩余的参数传递给构造函数(class) */
        /* 关键:执行函数Constructor(arguments),并绑定内部的 this */
        let instance = Constructor.apply(o, arguments);
    
        /* [5] 处理返回值 */
        /* 说明:如果是引用类型的数据那么就直接返回,否则总是返回内部新创建的对象 o */
        return instance instanceof Object ? instance : o;
    }
    
    
    /* 02-提供构造函数(首字母大写区分) */
    function Person(name, age) {
        this.age = age;
        this.name = name;
        this.showName = function() {
            console.log("姓名:" + this.name);
        }
        this.showAge = function() {
            console.log("年龄:" + this.age);
        }
    }
    
    /* 03-设置原型对象 */
    Person.prototype.showInfo = function() {
        this.showName();
        this.showAge();
    }
    
    /* 04-测试代码 */
    let p1 = mockNew(Person, "Yong", 16);
    let p2 = mockNew(Person, "Yi", 18);
    console.log(p1, p2);
    // Person { age: 16, name: 'Yong', showName: [Function], showAge: [Function] }
    // Person { age: 18, name: 'Yi', showName: [Function], showAge: [Function] }
    
    p1.showInfo();
    /* 姓名:Yong 年龄:16 */
    
  • 相关阅读:
    Bellman-Ford算法
    POJ 1990 MooFest
    POJ3067:Japan(树状数组求逆序对)
    树状数组求逆序对
    树状数组
    Is It A Tree?(hdu1325)
    强连通图 Tarjan算法
    UVALive
    UVALive
    Problem Statement
  • 原文地址:https://www.cnblogs.com/wendingding/p/15756510.html
Copyright © 2011-2022 走看看