zoukankan      html  css  js  c++  java
  • js原型链小总结

    最近在刷掘金的时候,发现有人发js原型继承方面的东西。关于js原型集成,我在刚学js的时候也比较浅入的研究过,当时是记住了,到现在我依旧是很模糊,于是乎我决定研究一次,并将结果记录下来,方便以后查阅。

    JavaScript 常被描述为一种基于原型的语言 (prototype-based language)——每个对象拥有一个原型对象,对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法。


    准确地说,这些属性和方法定义在Object的构造器函数(constructor functions)之上的prototype属性上,而非对象实例本身。


    在传统的 OOP 中,首先定义“类”,此后创建对象实例时,类中定义的所有属性和方法都被复制到实例中。在 JavaScript 中并不如此复制——而是在对象实例和它的构造器之间建立一个链接(它是__proto__属性,是从构造函数的prototype属性派生的),之后通过上溯原型链,在构造器中找到这些属性和方法

    以上是来自于 MDN 对js中原型的描述。

    __proto__prototype 区别

    我们可以通过 __proto__ 或者 Object.getPrototypeOf(obj) 来获取一个对象的原型对象,从而实现自下向上通过原型链来查找方法和属性,而 prototype 是一个对象通过new操作符来创建一个新对象的时候,赋予新对象 __proto__ 属性,也就是上面括号中加粗文本的总结。

    ( new Foo ).__proto__ === Foo.prototype
    ( new Foo ).prototype === undefined
    

    Object.O1='';
    Object.prototype.Op1='';
    
    Function.F1 = '';
    Function.prototype.Fp1 = '';
    
    Cat = function(){};
    Cat.C1 = '';
    Cat.prototype.Cp1 = '';
    
    mycat = new Cat();
    o = {};
    
    // EDITED: using console.dir now instead of console.log
    console.dir(mycat);
    console.dir(o);
    

    测试以上代码我们可以发现上图的原型链关系。

    这其中最奇怪的是: Object.__proto__ === Function.prototype, 而不是 Object.prototype,这表明 Object 是 Function的实例。

    Object是夏娃,Function是亚当,亚当(Function)使用它的第七根肋骨(Function.prototype)创造了夏娃(Object)。但是又是谁创造了亚当(Function)呢? 肯定不是神。。。答案就是创建js语言的作者(也就是:世界上根本没有神,只是某些人做到了普通人办不到的事情...)

    实际上 Object 类是 Function的实例。比如正常的Foo类是Function的实例,Foo.__proto__ === Function.prototype。原因:当我们在js中创建一个类的时候,我们直接上就是创建一个函数(function,我们能进行new操作的,其类型都是function),它应该是Function的实例(Function本身也是一个函数)。Object和Function都比较特殊,实际上他们都是正常的Foo类本质一样。

    因此,下边的四个值中的任意一个都(===)其他3个

    Function.prototype
    Function.__proto__
    Object.__proto__
    Cat.__proto__
    

    这也就意味着,我们往Function.prototype上添加属性,也会自动添加到对象__proto__为Function.prototype的一些对象(Date,Array,Number,Object,Boolean,String,Event,Error,RegExp)上:

    Function.prototype.address = 'china'
    "china"
    
    Array.address
    "china"
    
    Object.address
    "china"
    

    现在我们原型从Foo.__prototype__Function.__proto__ ,我查看下 Function.__proto__ 的类型:

    typeof Function.__proto__
    "function"
    

    啊!是不是惊呆了,我们一直说原型对象,类型竟然不是对象。。。以下是 ECMAScript 5 定义:

    15.3.4 Properties of the Function Prototype Object


    Function 原型对象是一个函数对象([class] Function),当在调用时,接收任何参数并且返回 undefined

    原型链我们追溯到了 Function.__proto__ ,我们知道 Function.__proto__ === Function.prototype,并且此时的类型是function,我们再往上找 只能是 Function.__proto__.__proto__ ,也就是 Function.prototype.__proto__,

    typeof Function.prototype.__proto__
    "object"
    
    typeof Object.prototype
    "object"
    

    目前我们发现,这俩货居然类型一样,莫非。。。没错:函数也是对象,Function.prototype(类型是function)也是Object的实例

    Object.prototype === Function.prototype.__proto__
    true
    

    我们查找原型链目前是 Foo.__prototype__, Function.__proto__, Function.__proto__.__proto__(Object.prototype),好嘛,终于跟Object扯上关系了,好,我们接着往上找,

    Object.prototype.__proto__
    null
    

    我直呼好家伙,终于到头了

    最后附上两种总结图:

  • 相关阅读:
    git
    java网络
    配置本地git服务器(gitblit win7)
    atom 插件安装【转载】
    javaIo
    如何在eclipse中设置断点并调试程序
    如何将工程推到github上
    git操作记录
    编码
    node升级7.0以上版本使用gulp时报错
  • 原文地址:https://www.cnblogs.com/hanshuai/p/14737274.html
Copyright © 2011-2022 走看看