美文网首页
如何实现一个 new

如何实现一个 new

作者: 三文治z | 来源:发表于2019-10-16 23:01 被阅读0次

    在调用 new 的过程中会发生以下四件事情:

    1.新生成了一个对象
    2.链接到原型
    3.绑定 this
    4.返回新对象

    function create() {
      let obj = {}                       // 创建一个空对象
      let Con = [].shift.call(arguments) // 获取构造函数
      obj.__proto__ = Con.prototype      // 设置空对象的原型
      let result = Con.apply(obj, arguments)           // 绑定 this 并执行构造函数
      return result instanceof Object ? result : obj   // 确保返回值为对象
    }
    
    function Dog(name) {
        this.name = name
        this.say = function () {
           console.log('name = ' + this.name)
        }
    }
    const dog = create(Dog, 'aaa')
    dog.say()  // name = aaa
    console.log(dog instanceof Dog)  // true
    

    补充 [].shift.call( arguments ) 和 [].slice.call( arguments )

    1. [].shift.call( arguments )
    [].slice.call( arguments )
    // 等效于
    Array.prototype.slice.call( arguments )
    
    • 要把 arguments 转为数组对象。
      本着 能少写就少写,能不写就不写的想法,想到 slice(): 可从已有的数组中返回选定的元素。
      slice 不会改变原来的数组,而是返回一个子数组。
      arguments 不是数组对象,不能调用数组的方法。
      但是能少写就少写,能不写就不写
    • 这时候又要解锁一个 call 函数,或者 apply 函数。这两个函数都可以改变函数 this 的指向,函数运行时的作用域。
      区别:就是参数不一样,第1个参数都是一个对象或者 ‘this’ 注意 this 加引号了, apply 第 2 个参数接收一个数组,call 则不是,call可以有n个参数有多少放多少就行。
    • slice 方法原理:根据传入的参数(值)对原数组(或者类数组)进行遍历获取,赋给新数组然后返回。如果没有参数便复制整个原数组(或者类数组),后赋给新数组然后返回
      重点来了
      因为 slice 内部实现是使用的 this 代表调用对象。那么当** [].slice.call() ** 传入 arguments 对象的时候,通过 call 函数改变原来 slice 方法的 this 指向, 使其指向arguments,并对 arguments 进行复制操作,而后返回一个新数组。至此便是完成了arguments 类数组 转为 数组 的目的。
    2. [].shift.call( arguments )
    [].shift.call( arguments )
    // 等效于
    Array.prototype.shift.call( arguments )
    

    shift() 方法删除数组第一项,并返回删除项。
    根据上边的理解,这句代码意思就是: “删除并拿到 arguments 的第一项”

    相关文章

      网友评论

          本文标题:如何实现一个 new

          本文链接:https://www.haomeiwen.com/subject/inspmctx.html