zoukankan      html  css  js  c++  java
  • 你不知道的JavasScript上篇·第五章·原型·上

    1、[[Prototype]]

    JS中的对象有一个特殊的[[Prototype]]内置属性,其实就是对于其他对象的引用。几乎所有的对象在创建时这个属性都被赋予一个非空的值 (proto

    var myObject = {
        a:2
    }
    myObject.a;//2
    

    查找a的过程:第一步默认[[Get]]操作检查myObject本身有没有这个属性,有的话就直接用自身的,没有就要继续访问对象的[[Prototye]]链

    使用for...in遍历对象时,原理和[[Prototype]] 类似,任何可以通过原型链访问到且enumerable为true的属性都会被枚举;
    使用in操作符来检查属性在对象中是否存在,检查对象自身&原型链

    所有普通的[[Prototype]]链最终都会指向内置的Object.prototype。Object.prototype对象包含js中许多通用的功能,如.toString(),.valueOf(),.hasOwnProperty()

    2、属性设置和屏蔽

    myObject.foo = 'bar'
    

    这条语句详细执行过程:

    如果myObject中包含名为foo的普通属性,这条语句就是修改已有属性值
    如果foo从未出现过(包含在[[Prototype]]上),则直接添加在myObject
    如果foo既出现在原型链上也出现在myObject上,myObject中的foo会屏蔽原型链上的foo

    如果foo不直接存在于myObject中而是存在于原型链上层时,myObject.foo = 'bar' 出现的三种情况:

    1. 如果[[Prototype]] 链上层存在的foo,并没有标记为只读(writable:false),就直接在myObject中添加一个名为foo的属性,它是屏蔽属性
    2. 如果[[Prototype]] 链上层存在foo,但是被标记为只读,那么无法修改已有属性或者在myObject创建屏蔽属性。在严格模式下还会报错,否则会被忽略
    3. 如果[[Prototype]] 链上层存在foo,并且是一个setter,那么foo值会直接更新,不会被添加到myObject上

    但是,有些情况下会隐式产生屏蔽,譬如下面的代码:

        var anotherObject = {
            a:2
        }
        var myObject = Object.create(anotherObject);
        anotherObject.a;//2
        myObject.a;//2
        myObject;//
    

    myObject:

        anotherObject.hasOwnProperty('a');true
        myObject.hasOwnProperty('a');//false
        myObject.a++;
        anotherObject.a;//2
        myObject.a;//3
        myObject.hasOwnProperty('a');//ture
    

    神奇吧,myObjec.a经过++运算后myObject.hasOwnpProperty('a');变成true了
    这是因为++操作相当于myObject.a = myObject.a+1;查找属性会通过[[Prototype]]找到anotherObject.a的值2,然后给这个值加1
    接着用[[Put]]赋给myObject中新建的屏蔽属性a

    3、“类”函数

    所有的函数默认都会拥有一个名为prototype的共有并且不可枚举的属性,指向另一个对象。
    这个对象通常被称为原型

        function Foo(){
            ...
        }
        Foo.prototype;//{}
    

    一起看下一个例子:

     function Foo(){
         ...
     }
     var a = new Foo();
     Object.getPrototypeOf(a) === Foo.prototype;//true
    

    调用new Foo()时,会创建a,其中一步就是将a内部的[[Prototype]]链接到Foo.prototype所指的对象。

    Object.getPrototypeof()和Object.setPrototypeof()的用法

    Object.getPrototypeOf(目标对象) 获取目标对象的原型链上的值

    Object.setPrototypeOf(目标对象,要将原型链关联的对象)

    new Foo()这个含糊调用实际上并没有直接创建关联,只是间接完成了我们的目标:关联到其他对象的新对象
    做到这点更加直接的方式:Object.create(目标对象)

    4、继承

    继承意味着复制操作;

    差异继承:
    基本原则是在描述对象行为时,使用其不同于普遍描述的特制。 (我的理解是只用对象自身的而不用普遍继承的像是toString(),valueOf()这种方法)

  • 相关阅读:
    Teamplate Workflow Architecture(Teamplate工作流架构)
    Las Vegas拉斯维加斯(赌城)游记
    初步尝试Teamplate Workflow Web Part for SharePoint Portal Server
    灵活管理Remote Objects生存期(lifetime)
    Wincv.exe类查看器工具(Class Viewer)
    重构(Refactoring)技巧读书笔记 之二
    重构(Refactoring)技巧读书笔记 之一
    尝试RemotingSqlHelper的若干问题
    关于ADO.Net连接池(Connection Pool)的一些个人见解
    SQL Server 最佳实践分析器使用小结
  • 原文地址:https://www.cnblogs.com/angfl/p/10234216.html
Copyright © 2011-2022 走看看