美文网首页
自我解惑---JavaScript原型链,涉及new,typeo

自我解惑---JavaScript原型链,涉及new,typeo

作者: 煮黑豆 | 来源:发表于2020-12-24 16:17 被阅读0次
    image.png

    验证上图原型链是否正确

    console.log(Object.__proto__===Function.prototype,
    Function.__proto__===Function.prototype,
    Array.__proto__===Function.prototype,
    String.__proto__===Function.prototype,
    Number.__proto__===Function.prototype,
    Boolean.__proto__===Function.prototype,
    Date.__proto__===Function.prototype,
    RegExp.__proto__===Function.prototype,
    Error.__proto__===Function.prototype)
    // true true true true true true true true true
    

    对象拥有 “proto” 属性,函数没有此属性,函数则拥有 prototype属性
    对象可由函数生成
    当我们生成一个对象时,对象中的”proto”属性则指向函数prototype属性—(默认值)

    在上图中,有proto,什么可以设置了proto链接呢?
    new、Object.create()和Object.setPrototypeOf(obj, prototype)可以设置proto

    Object.setPrototypeOf(obj, prototype)语法知识
    obj:可以是一个对象,也可以是一个函数
    prototype:null或者一个对象
    说明一下,proto这种写法是浏览器厂商自己的实现。

    new底层实现原理

    前提知识:构造函数有return和没有return两种情况。
    构造函数里没有显式调用return时,默认是返回this对象,也就是新创建的实例对象。
    当构造函数里调用return时,分两种情况:
    1.return的是五种简单数据类型:String,Number,Boolean,Null,Undefined。
    这种情况下,忽视return值,依然返回this对象。
    2.return的是Object,这种情况下,不再返回this对象,而是返回return语句的返回值。
    下面是无return的实现原理:

    1、创建一个新空对象
    2、将构造函数的prototype赋值给新对象的proto
    3、将构造函数的this指向该新对象
    4、执行构造函数的代码语句
    5、返回这个空对象

    原理代码实现

    _new = function() {
        var obj = {};
        obj.__proto__ = _new.prototype;
        _new.call(obj);
        //将构造函数的this执行该新对象
        return obj;
    }
    
    

    验证上述实现原理:

    function Fn() {
        this.age = "chenxinhui";
    }
    Fn.prototype.study = function() {
        console.log("验证new")
    }
    var fn = new Fn();
    console.log(fn.__proto__ === Fn.prototype)
    //true
    

    console.dir(fn)

    image.png
    可以看出实例fn对象的proto指向了构造函数Fn的prototype属性。
    再来一个例子验证构造函数的this的proto指向构造函数的prototype
    var _ = function(obj) {
        if (obj instanceof _) return obj;
        if (!(this instanceof _)) return new _(obj);  //执行new之后,this.__proto__===_.prototype             
        this._wrapped = obj;
    };
    
    var obj1=new _();
    console.log(obj1);
    
    image.png

    验证上述问题,你可能对instanceof到底做了什么感到疑惑,那咱再来分析分析它的底层实现原理。
    先说明以下结论

    1、js规定,访问对象属性的时候,如果该对象下面没有这个属性,则去它下面的proto属性去寻找,如果还是没有就一直向下寻找,直到没有proto为止,即执行null
    2、instanceof关键字返回boolean值,从左侧值引用的proto一层一层寻找,看右侧的prototype是否在左侧的原型链中

    instanceof底层源码实现原理

    function _instanceof(L, R) {
        var rv = R.prototype;
        L = L.__proto__;
        while (true) {
            if (L === null)
                return false;
            if (rv === L)
                return true;
            L = L.__proto__;
        }
    }
    
    

    验证上述原理

    function Father() {}
    function Son() {}
    Son.prototype = new Father();
    //此处注意Son.prototype对象重新赋值,和Son.prototype.eat=function(){}区别
    
    var son=new Son();
    
    console.log(son instanceof Son)//true
    console.log(son instanceof Father)//true
    
    image.png

    console.log(son instanceof Son)验证逻辑

    function _instanceof(L, R) {//L为son,R为Son
        var rv = R.prototype;//rv即为Son.prototype,指向了father
        L = L.__proto__;//L指向了father
        while (true) {
            if (L === null)
                return false;
            if (rv === L)//通过,返回true
                return true;//此时,两方都指Father的实例对象father,所以true
            L = L.__proto__;
        }
    }
    
    

    console.log(son instanceof Father)验证逻辑

    function _instanceof(L, R) {//L为son,R为Father
        var rv = R.prototype;//rv即为Father.prototype,指向了father
        L = L.__proto__;//L指向了father
        while (true) {
            if (L === null)
                return false;
            if (rv === L)//第一次循环不通过
                 // 第二次循环son.__proto__.__proto__指向Father.prototype,通过,返回true
                return true;
            L = L.__proto__;//将L= L.__proto__.__proto__指向Father.prototype,继续循环                           
        }
    }
    
    

    typeof

    typeof返回值字符串,具体有"object","function","number","string","boolean","underfined",
    es6中新增了"symbol",es10新增"bigint"
    其中

    typeof  []==="object"//true
    typeof null==="object"//true
    typeof {}==="object"//true
    

    apply和call

    他们负责改变this的指向,他们两个的区别就是参数类型不同

    apply(obj,array)//第二个参数记忆技巧,apply首字母和array首字母一样,为数组
    call(obj,arg1,arg2,....)//
    

    另外一些小知识点:
    this要在执行时才能确认值,定义时无法确认。
    函数执行上下文:

    一段<script>中或者一个函数之内都会生成“执行上下文”
    针对<script>,会生成全局的执行上下文,将变量声明、函数声明拿出来
    针对一个函数,会生成函数执行上下文,在函数执行之前,将函数内的变量声明、函数声明、this、arguments拿出来
    还要注意函数表达式不会生成执行上下文
    函数声明: function fn() {…}
    函数表达式:var a = function(){…},相当于执行了两部
    var a;
    a=funcition(){}

    相关文章

      网友评论

          本文标题:自我解惑---JavaScript原型链,涉及new,typeo

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