• js原型链接(二)和object类的create方法


    原型链的内部执行方式

    <script>
    function Myclass(){
        this.x=" x in Myclass";
    }
    var obj=new Myclass();
    p(obj.x);
    p(obj.z); //undefined
    Myclass.prototype.z="z in Myclass";
    p(obj.z);
    //首先查找自身属性,如果没有找到 将沿着原型链接 查找构造函数(Myclass)的prototype对象里找
    </script>

    属性的重写与删除与原型链无关

    <script>
    function Myclass(){
        this.x=" x in Myclass";
    }
    Myclass.prototype.y="y in Myclass";
    var obj=new Myclass();
    p(obj.y);//y in Myclass
    obj.y="override y";
    p(obj.y);//override y
    delete obj.y //true
    p(obj.y);//y in Myclass
    var obj2=new Myclass();
    p(obj2.y);//y in Myclass
    obj.z='zzz';  
    p(obj.z);//zzz
    p(obj2.z);//undefined
    p(obj.prototype);//undefined
    </script>

    获取原型对象的三种方法

    <script>
    function Myclass(){}
    var proto=Myclass.prototype;
    var obj=new Myclass();
    //通过第五版里加强
    var proto=Object.getPrototypeOf(obj);
    //通过对象实例获得
    var proto=obj.__proto__;
    //通过对象实例以及其构造函数
    var proto=obj.constructor.prototype;
    p(obj.constructor==Myclass); //true
    </script>

    通过constructor判定数据类型

    <script>
    var d=new Date();
    p(d.constructor);//function Date() { [native code] }
    var arr=[1,2,3];
    p(arr.constructor);//function Array() { [native code] }
    var obj={};
    p(obj.constructor);//function Object() { [native code] }
    </script>

    constructor属性并不是对象的直接属性,而是通过原型链接 查找到的
    每个对象在创建时 构造器会执行这样一句代码
    this.prototype=
    {
    constructor:this,
    __proto__:Object.prototype
    }
    通过改变prototype实现继承

    <script>
    function Derived(){}  //创建时 就有了Derived.prototype={constructor:Derived}
    p(Derived.prototype.__proto__==Object.prototype);//true
    p(Derived.__proto__);//function Empty() {}
    function Base(){} //原理同上
    Derived.prototype=new Base();
    //此时Derived.prototype的原型链接__proto__改变了指向
    p(Derived.prototype.__proto__==Base.prototype); //true
    var obj=new Derived();
    //此时
    p(obj.__proto__==Derived.prototype);//true
    //现在obj里找 ,没有,到Derived.prototype引用的对象Base里找,没有,就到Base.prototype里找了
    p(obj.constructor); //function Base(){}
    </script>

    数据类型判定(instanceof与isPrototypeOf)

    <script>
    var d=new Date();
    p(Date.__proto__);////function Empty() {}
    p(d instanceof Date);//true
    p(d instanceof Object);//true
    p(Date instanceof Object);//true
    p(Object instanceof Date);//false
    
    function Derived(){}
    function Base(){}
    Derived.prototype=new Base();
    var obj=new Derived();
    p(obj instanceof Derived);//true
    p(obj instanceof Base); //true
    p(Derived instanceof Base);//false   Derived不是由 Base构造函数生成的
    p(Derived.constructor);//function Function() { [native code] }
    p(Derived instanceof Object);//true
    
    p(Derived.prototype.isPrototypeOf(obj)); //true
    Base.prototype.isPrototypeOf(obj);//true
    Object.prototype.isPrototypeOf(obj)//true
    </script>

    属性的枚举
    in 可以可判断本身属性和通过继承来的属性 是否存在于某个对象
    hasOwnProperty只列出本身可以枚举的属性
    有些属性被枚举出来是因为enumerable属性为false
    getOwnPropertyNames可以无视枚举属性,列举出所有属性

    <script>
    var obj={x:1,y:2};
    p(Object.keys(obj));//x,y
    obj.z=3;
    //obj.prototype.p='pp';//实例 prototype属性
    p(obj.prototype);//undefined
    p(obj.__proto__==Object.prototype); //true
    p(Object.keys(obj));//x,y,x
    var arr=[1,2,3];
    p(Object.keys(arr)); //0,1,2
    p(Object.getOwnPropertyNames(arr)); //0,1,2,length
    p(Object.keys(Object.prototype));//
    p(Object.getOwnPropertyNames(Object.prototype));
    /*
    constructor,toString,toLocaleString,valueOf,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,__defineGetter__,__lookupGetter__,__defineSetter__,__lookupSetter__,__proto__
    */
    //对于enumerable可根据propertyIsEnumerable来判断
    function Myclass(){
        this.x=1;this.y=2;
    }
    Myclass.prototype.z=3;
    var obj=new Myclass();
    p(Object.getOwnPropertyNames(obj)); //x,y 不列举通过继承获取的属性
    p(Object.keys(obj));// x,y
    for(var key in obj){
        p(key);
    }
    //x,y,z
    </script>

    ECMAScript里的Object类
    Object里的create方法,是除了对象字面量与new表达式之外的第三种官方的生成对象的方法
    第一个参数需要一个原型对象,第二个参数需要一个属性对象
    如果将一个null作为原型传递给create方法 ,则会生成一个没有进行原型继承的对象

    <script>
    var obj=Object.create(null);
    p(Object.getPrototypeOf(obj));//null
    p("toString" in obj);//false
    var obj=Object.create(Object.prototype);
    //
    var obj={};
    //等效
    p(obj.__proto__===Object.prototype);//true
    p(obj.constructor==Object);//true
    
    function Myclass(){}
    var Proto={x:2,y:3};
    Myclass.prototype=Proto;
    var obj=new Myclass();
    //下面代码等价
    var Proto={x:2,y:3};
    var obj=Object.create(Proto);
    </script>

    属性对象
    create方法的第二个参数是一个关联数组,其键为属性名,其值为属性描述符(属性对象)
    属性描述符指由下表中的 由属性组成的关联数组

    属性对象
    create方法的第二个参数是一个关联数组,其键为属性名,其值为属性描述符(属性对象)
    属性描述符指由下表中的 由属性组成的关联数组

    属性的属性名

    含义

    writable

    可以改写属性的值

    enumerable

    可以通过for in枚举出

    configurable

    可以改变属性的属性,可以删除属性

    get

    可以指定属性值的getter函数

    set

    可以指定属性值的setter函数

    属性值通过value属性指定.大部分属性的默认值是false,也可以显示地指定为true

    <script>
    var obj={x:2,y:3};
    //与下面代码
    var obj=Object.create(Object.prototype,
    {
    x:{value:2,writable:true,enumerable:true,configurable:true},
    y:{value:2,writable:true,enumerable:true,configurable:true}
    }
    );
    // 是等效的
    </script>

    与Object类的属性的属性有关的方法

    方法

    说明

    defineProperty(o,p,attributes)

    向对象o增加/更新具有特定信息的属性p

    defineProperties(o,properties)

    向对象o增加/更新具有特定信息的属性

    getOwnPropertyDescriptior(o,p)

    返回对象o的直接属性p的信息(值与属性)

    <script>
    var obj=Object.create(Object.prototype,{x:{value:2}});
    //除了显式指定的属性,其它的值都为false  value默认为undefined
    Object.getOwnPropertyDescriptor(obj,'x');
    //{value:2,writable:false,enumerable:false,configurable:false}
    //新增属性y
    Object.defineProperty(obj,'y',{value:3,enumerable:true});
    Object.getOwnPropertyDescriptor(obj,'y');
    //{value:3,writable:false,enumerable:true,configurable:false}
    // 新增属性z
    Object.defineProperties(obj,
        {
            z:{value:function(){alert('z called');},enumerable:true}
        }
    );
    Object.getOwnPropertyDescriptor(obj,'z');
    //{value:function(){alert('z called');},enumerable:true,configurable:false,writable:false}
    </script>

    如果属性的configurable属性为true,可以更改包括值在内的所有属性,反之如果为false,则不能
    由于此时configurable的属性页无法更改,这是其实是无法进行任何更改的.

  • 相关阅读:
    官方下载python源码,编译linux版本的python
    bootstrap冻结窗口
    LeetCode之TwoSum
    MyISAM和InnoDB索引实现对比(总结)
    InnoDB的三个关键特性(总结)
    InnoDB与MyISAM总结和对比(总结)
    C++类库开发之导出类设计原则
    C++类库开发详解
    C#各种配置文件使用,操作方法总结
    C/C++代码优化的27条建议
  • 原文地址:https://www.cnblogs.com/HKUI/p/4127383.html
Copyright © 2020-2023  润新知