最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • new操作符原理及实现

    正文概述 掘金(前端橘子君)   2020-12-08   475

    new 的用法

    // 定义构造函数
    function Person (name) {
      this.name = name;
    }
    
    Person.prototype.age = 26;
    
    // 创建实例
    var person = new Person('前端橘子君');
    
    // 调用实例
    console.log(person.name); // 前端橘子君
    console.log(person.age); // 26
    console.log(person); // Person {name: "前端橘子君"}
    

    这是一个很普通的实例,他们分别调用了实例和原型上的属性。

    原理

    根据JavaScript高级程序设计第六章构造函数模式中所写,使用new操作符创建实例会经过4个阶段:

    • 1、创建一个新对象
    • 2、将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象)
    • 3、执行构造函数中的代码(为这个新对象添加属性)
    • 4、返回新对象

    既然知道了步骤,那么我们就可以实现了。

    实现

    可能第二步比较难以理解,需要了解原型和原型链知识,详情可参考:原型及原型链。

    我们先不管第二步,实现一个初始版本。

    /**
     * 实现new操作符
     * @param ctor 构造函数
     * @param args 构造函数需要的参数
    */
    function _new (ctor, ...args) {
      // 第一步,创建新对象
      var obj = {};
      // 第二步,忽略
      
      // 第三步,执行构造函数,并将构造函数的初始属性都挂载在新对象上
      ctor.call(obj, ...args);
      // 返回新对象
      return obj;
    }
    
    // 定义构造函数
    function Person (name) {
      this.name = name;
    }
    // 向构造函数的原型添加属性
    Person.prototype.age = 26;
    
    // 调用
    var person = _new(Person, '前端橘子君')
    console.log(person.name); // 前端橘子君
    console.log(person.age); // 26
    

    我们可以看到,我们可以调用实例的属性name,但是没法调用Person原型上的属性age,why?

    因为person不在Person的原型链上,换句话说,person并不是Person的实例,验证一下。

    console.log(person instanceof Person); // false
    

    不要奇怪,我们先来看看personPerson的原型链

    person和Person的原型链

    不熟悉原型和原型链的请参考:原型及原型链,用最通俗易懂的语言教你了解什么是原型和原型链。

    person的原型链:person实例 -> Object.prototype -> null

    Person的原型链:构造函数Person -> Object.prototype -> null

    我们所期望的原型链:person实例 -> 构造函数Person -> Object.prototype -> null

    完整代码

    既然我们知道了我们想要的原型链,通过观察,我们知道,只要将person实例的原型链(__proto__)指向构造函数Person的原型不就可以了么?

    obj.__proto__ = ctor.prototype

    这不就是第二步需要做的操作么?放进去再试试吧。

    /**
     * 实现new操作符
     * @param ctor 构造函数
     * @param args 构造函数需要的参数
    */
    function _new (ctor, ...args) {
      // 第一步,创建新对象
      var obj = {};
      // 第二步,忽略
      obj.__proto__ = ctor.prototype
      // 第三步,执行构造函数,并将构造函数的初始属性都挂载在新对象上
      ctor.call(obj, ...args);
      // 返回新对象
      return obj;
    }
    
    // 定义构造函数
    function Person (name) {
      this.name = name;
    }
    // 向构造函数的原型添加属性
    Person.prototype.age = 26;
    
    // 调用
    var person = _new(Person, '前端橘子君')
    console.log(person.name); // 前端橘子君
    console.log(person.age); // 26
    console.log(person instanceof Person); // true
    

    更多相关文档,请见:

    线上地址 【前端橘子君】

    GitHub仓库【前端橘子君】


    起源地下载网 » new操作符原理及实现

    常见问题FAQ

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

    发表评论

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

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

    联系作者

    请选择支付方式

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