• javascript中构造器(函数)的__proto__与prototype初探


    背景:最近没什么需求,快要闲出屁了,所以重温了一下js的原型,结果大有收获,且偶然看到Snandy大神的《JavaScript中__proto__与prototype的关系》

    这篇文章,感觉真是受益匪浅,原文出处:http://www.cnblogs.com/snandy/archive/2012/09/01/2664134.html

    ****前戏结束,开始正题****

    一.所有构造器/函数的__proto__都指向Function.prototype(Function.prototype是一个空函数)

    如何验证这句话呢?最好的方式就是上代码:

    //内置的构造器
    console.log(Number.__proto__===Function.prototype);    //true
    
    //自定义的函数
    var func=function(){};
    function Person(name){
       this.name=name
    }
    console.log(func.__proto__===Function.prototype);       //true
    console.log(Person.__proto__===Function.prototype);    //true

    这是为什么呢?我们接着上代码

    看到了吧,无论是内置的构造器,还是自定义的构造器或函数,他们都是函数,或者说是方法;方法的原型自然指向Function.prototype

    二.__protype__更像是构造器指向构造器的原型的一个指针;而prototype是构造器的一个属性,并且是一个对象(纯属个人看法)

    还是代码验证:

    图1

    图2

    我们可以看到Number没有__proto__属性,所以它更像是一个代码不可见的指针;而Number有prototype这个属性。

    三、所有对象的__proto__都指向其构造器的prototype(在没有手动覆盖构造器的prototype的情况下)

    首先,我们先看一下js内置构造器生成的对象:

    var obj = {name: 'jack'}
    var arr = [1,2,3]
    var reg = /hello/g
    var date = new Date
    var err = new Error('exception')
     
    console.log(obj.__proto__ === Object.prototype) // true
    console.log(arr.__proto__ === Array.prototype)  // true
    console.log(reg.__proto__ === RegExp.prototype) // true
    console.log(date.__proto__ === Date.prototype)  // true
    console.log(err.__proto__ === Error.prototype)  // true

    再看看自定义构造器生成的对象:

    //这里定义了一个Person构造器
    function Person(name) {
        this.name = name
    }
    var p = new Person('jack')
    console.log(p.__proto__ === Person.prototype) // true

    由此可见,所有对象的__proto__都指向其构造器的prototype,但是这句话是什么意思呢?“在没有手动覆盖构造器的prototype的情况下”,说到这儿了,那我们就接着

    往下看,通常我们将属性写在构造器中,将方法写在构造器的原型里面(将方法写在原型中通常有2种方式)

    (1)动态的为构造器的原型添加方法

    function Person(name) {
        this.name = name
    }
    // 修改原型
    Person.prototype.getName = function() {}
    var p = new Person('jack')
    console.log(p.__proto__ === Person.prototype) // true
    console.log(p.__proto__ === p.constructor.prototype) // true

    (2)完全重写构造器的原型

    function Person(name) {
        this.name = name
    }
    // 重写原型
    Person.prototype = {
        getName: function() {}
    }
    var p = new Person('jack')
    console.log(p.__proto__ === Person.prototype) // true
    console.log(p.__proto__ === p.constructor.prototype) // false

    以第一种方式为构造器的原型动态增加方法时,原型的constructor属性始终指向该构造器;而方法二则完全重写了构造器的原型,导致对象实例访问constructor时,在构造

    器中找不到,在原型中也找不到,最终追溯到了Object.prototype。如下图所示:

    图1

    图2

    看到了吧,构造器的原型是可以重写的,重写后prototype已经不是原先的prototype了(你大妈已经不是你原先的大妈了,你大爷还是你大爷,哈哈O(∩_∩)O哈哈~),

    导致原先指向构造器的constructor属性不见了,所以对象实例在访问constructor时,吧啦吧啦,我就不重复说了,前面已经说过了。

    ********注:上面代码中用到的__proto__目前在IE6/7/8/9中都不支持,IE9中可以使用Object.getPrototypeOf(ES5)获取对象的内部原型。********

    var p = {}
    var __proto__ = Object.getPrototypeOf(p)
    console.log(__proto__ === Object.prototype) // true

    四、个人精辟总结(其实是在js高级程序设计中看到的)

    实例的__proto__总是指向其构造函数的prototype,__proto__是实例与构造函数的原型之间的关系,而不是实例与构造函数之间的关系

  • 相关阅读:
    DIV+CSS列表式布局(同意图片的应用)
    Cache 应用程序数据缓存
    mysql 中 isnull 和 ifnull 判断字段是否为null
    Logo图标快速生成软件(Sothink Logo Maker) v3.5 官方设计师版
    Linqer工具
    mvc学习视频
    MvcPager注意版本与mvc的版本
    此版本的 SQL Server 不支持用户实例登录标志。该连接将关闭“的解决
    ASP.NET 免费开源控件
    逆向知识之CS1.6辅助/外挂专题.1.实现CS1.6主武器副武器无限子弹
  • 原文地址:https://www.cnblogs.com/webjoker/p/5319377.html
Copyright © 2020-2023  润新知