• JavaScript中new实现原理


    一、JavaScript中new实现原理
    1、创建一个空对象 obj
    2、将该对象 obj 的原型链 __proto__ 指向构造函数的原型 prototype,
    并且在原型链 __proto__ 上设置 构造函数 constructor 为要实例化的 Fn
    3、传入参数,并让 构造函数 Fn 改变指向到 obj,并执行
    4、最后返回 obj
     
     
    二、例子:
    构造函数
    function Parent(age, name) {
        this.age = age
        this.name = name
        this.sayAge = function() {
            console.log('this.age :', this.age)
        }
    }
    Parent.prototype.sayName = function() {
        console.log('this.name :', this.name)
    }
    模拟 new 运算符功能函数
    function New(Fn) {
        let obj = {}
        let arg = Array.prototype.slice.call(arguments, 1)
        obj.__proto__ = Fn.prototype
        obj.__proto__.constructor = Fn
        Fn.apply(obj, arg)
        return obj
    }
    三、测试
    let son = new Parent(18, 'lining')      
    let newSon = New(Parent, 18, 'lining')
    
    console.log('son :', son)       // son : Parent { age: 18, name: 'lining', sayAge: [Function] }
    console.log('newSon :', newSon) // newSon : Parent { age: 18, name: 'lining', sayAge: [Function] }
    
    console.log('son.constructor :', son.constructor)
    // son.constructor : function Parent(age, name) {
    //     this.age = age
    //     this.name = name
    //     this.sayAge = function() {
    //         console.log('this.age :', this.age)
    //     }
    // }
    
    console.log('newSon.constructor :', newSon.constructor)
    // newSon.constructor : function Parent(age, name) {
    //     this.age = age
    //     this.name = name
    //     this.sayAge = function() {
    //         console.log('this.age :', this.age)
    //     }
    // }
     
    四、特殊情况
    上面的实现过程是一般我们所普遍知晓的构造过程
    但是在 JavaScript 实现中,如果构造函数返回的是个对象/原始类型
    那么最终得到的实例就不一样了
     
    各个返回类型情况:
    function Parent(age, name) {
        this.age = age
        this.name = name
        this.sayAge = function() {
            console.log('this.age :', this.age)
        }
        // return 0
        // return null
        // return undefined
        // return false
        // return true
        // return ''
        // return 'parent'
        // return Symbol('parent')
        // return []
        // return {}
        // return {
        //     hands: 2,
        //     foot: 2
        // }
    }
    Parent.prototype.sayName = function() {
        console.log('this.name :', this.name)
    }
    下面分别对应上面 11 种 return 情况
    return 0:
    let p1 = new Parent(18, 'jolin')
    console.log('p1 :', p1) // p1 : Parent { age: 18, name: 'jolin', sayAge: [Function] }
    
    return null:
    let p2 = new Parent(18, 'jolin')
    console.log('p2 :', p2) // p2 : Parent { age: 18, name: 'jolin', sayAge: [Function] }
    
    return undefined:
    let p3 = new Parent(18, 'jolin')
    console.log('p3 :', p3) // p3 : Parent { age: 18, name: 'jolin', sayAge: [Function] }
    
    return false:
    let p4 = new Parent(18, 'jolin')
    console.log('p4 :', p4) // p4 : Parent { age: 18, name: 'jolin', sayAge: [Function] }
    
    return true:
    let p5 = new Parent(18, 'jolin')
    console.log('p5 :', p5) // p5 : Parent { age: 18, name: 'jolin', sayAge: [Function] }
    
    return '':
    let p6 = new Parent(18, 'jolin')
    console.log('p6 :', p6) // p6 : Parent { age: 18, name: 'jolin', sayAge: [Function] }
    
    return 'parent':
    let p7 = new Parent(18, 'jolin')
    console.log('p7 :', p7) // p7 : Parent { age: 18, name: 'jolin', sayAge: [Function] }
    
    return Symbol('parent'):
    let p8 = new Parent(18, 'jolin')
    console.log('p8 :', p8) // p8 : Parent { age: 18, name: 'jolin', sayAge: [Function] }
    
    return []:
    let p9 = new Parent(18, 'jolin')
    console.log('p9 :', p9) // p9 : []
    
    return {}:
    let p10 = new Parent(18, 'jolin')
    console.log('p10 :', p10) // p10 : {}
    
    return {
        hands: 2,
        foot: 2
    }
    let p11 = new Parent(18, 'jolin')
    console.log('p11 :', p11) // p11 : { hands: 2, foot: 2 }
    因此实现原理改一下:
    1、创建一个空对象 obj
    2、将该对象 obj 的原型链 __proto__ 指向构造函数的原型 prototype,
    并且在原型链 __proto__ 上设置 构造函数 constructor 为要实例化的 Fn
    3、传入参数,并让 构造函数 Fn 改变指向到 obj,并执行
    4、如果 Fn 执行后返回的是对象类型(null除外),则返回该对象,否则返回 obj

    修改模拟 new 运算符功能函数

    function New(Fn) {
        let obj = {}
        let arg = Array.prototype.slice.call(arguments, 1)
        obj.__proto__ = Fn.prototype
        obj.__proto__.constructor = Fn
        let ret = Fn.apply(obj, arg)
        return typeof ret === 'object' ? ret || obj : obj
    }

    都读到最后了、留下个建议如何
  • 相关阅读:
    七月二十二日学习报告
    七月二十一学习报告
    七月二十学习报告
    补 七月十九学习报告
    七月十八学习报告
    iOS 逆向工程(三)之Xcode检测是否越狱成功
    iOS 逆向工程(二)之越狱手机安装必备软件
    iOS逆向工程(一)之手机越狱
    html练习 简单html页面
    集合对象序列化 反序列 IO 1将文件中的所有信息,通过合适的IO流读取出来,封装成Person对象,使用集合进行存储 2将集合对象序列化到另外一个文件persons.txt中 3从persons.txt反序列化其中的集合,并遍历集合内容
  • 原文地址:https://www.cnblogs.com/linjunfu/p/10791467.html
Copyright © 2020-2023  润新知