• JavaScript 对象


    function inherit(p){
        if(p == null) throw TypeError();
        if(Object.create)
            return Object.create(p);
        var t = typeof p;
        if(t !== "object" && t !== "function") throw TypeError();
        function f(){};
        f.prototype = p ;
        return new f();
    };

    创建对象

      对象创建的三种方式: 

        对象自面量、构造函数、ECMAScript5中引入的 Object.create()

        自面量的方式:

    var o = {name:"wj",age:"20"};

        构造函数:

    function FunctionName(){}

         Object.create()

    Object.create(proto, [ propertiesObject ])
    proto 一个对象,作为新创建对象的原型。
    propertiesObject
        可选。该参数对象是一组属性与值,该对象的属性名称将是新创建的对象的属性名称,值是属性描述符(这些属性描述符的结构与Object.defineProperties()的第二个参数一样)。
    注意:该参数对象不能是 undefined,另外只有该对象中自身拥有的可枚举的属性才有效,也就是说该对象的原型链上属性是无效的。

        如果 proto 参数不是 null 或一个对象值,则抛出一个 TypeError 异常。

    实例一:

    //Shape - superclass
    function Shape() {
      this.x = 0;
      this.y = 0;
    }
    
    Shape.prototype.move = function(x, y) {
        this.x += x;
        this.y += y;
        console.info("Shape moved.");
    };
    
    // Rectangle - subclass
    function Rectangle() {
      Shape.call(this); //call super constructor.
    }
    
    Rectangle.prototype = Object.create(Shape.prototype);
    
    var rect = new Rectangle();
    
    rect instanceof Rectangle //true.
    rect instanceof Shape //true.
    
    rect.move(1, 1); //Outputs, "Shape moved."

     

    实例二: proto属性与 propertiesObject 结合使用

      

    var o;
    
    // 创建一个原型为null的空对象
    o = Object.create(null);
    
    
    o = {};
    // 以字面量方式创建的空对象就相当于:
    o = Object.create(Object.prototype);
    
    
    o = Object.create(Object.prototype, {
      // foo会成为所创建对象的数据属性
      foo: { writable:true, configurable:true, value: "hello" },
      // bar会成为所创建对象的访问器属性
      bar: {
        configurable: false,
        get: function() { return 10 },
        set: function(value) { console.log("Setting `o.bar` to", value) }
    }})
    
    
    function Constructor(){}
    o = new Constructor();
    // 上面的一句就相当于:
    o = Object.create(Constructor.prototype);
    // 当然,如果在Constructor函数中有一些初始化代码,Object.create不能执行那些代码
    
    
    // 创建一个以另一个空对象为原型,且拥有一个属性p的对象
    o = Object.create({}, { p: { value: 42 } })
    
    // 省略了的属性特性默认为false,所以属性p是不可写,不可枚举,不可配置的:
    o.p = 24
    o.p
    //42
    
    o.q = 12
    for (var prop in o) {
       console.log(prop)
    }
    //"q"
    
    delete o.p
    //false
    
    //创建一个可写的,可枚举的,可配置的属性p
    o2 = Object.create({}, { p: { value: 42, writable: true, enumerable: true, configurable: true } });

     

    属性的查询和设置

       查询与设置两种方式: . 或 [] 方式

       对象给属性赋值时,首先会检查原型链上是否允许赋值操作。 如果 o 继承来的x是一个只读属性,那么是不允许赋值的,严格模式下会报错。 如果允许的话,只会在原对象上添加或修改,不会去修改原型链。

    案例一:通过字面方式定义属性,默认属性特性是: 可配置、可枚举、可读/可写

    var person = {name:"wj"};
    var o = inherit(person);
        o.name = "wjj";
        console.log(o.name); // wjj
         console.log(person.name); //wj

    案例二:defineProperty 修改 name 的特性时

    var person = {name:"wj"};
    Object.defineProperty(person,"name",{
        writable:false
    })
    var sub = inherit(person);
    sub.name = "wjj"; //TypeError: Cannot assign to read only property 'name' of object '#<Object>'
    console.log(sub.name);
    console.log(person.name);

       注意:1:JavaScript中,只有在查询属性时才会体会到继承的存在,在设置属性则和继承无关,这是JavaScript的一个特性,该特性让程序员可以有选择地覆盖(override)继承的属性。

          2:属性的赋值要么失败,要么创建一个属性,要么在原始对象中设置属性。

    删除属性

      delete  操作符 删除自有属性 并且是 configable:true; 

      delete 操作符只能删除自有属性,而不能删除继承属性(如果要删除继承属性必须通过原型对象来删除,删除同时所有继承该原型的对象都会受到影响)

    检测属性 与 枚举属性

      

     

    存取器属性 setter getter

       基本组成  

          enumerable
          configurable
          set
          get

         注意:存取器属性不具有可写性(writeable ), 如果属性同时拥有 set、get 则其可写、可读, 如果只 “set” 可写 如果只添加了 “get” 可读;

    属性的特性

      属性除了包含名字和值之外,属性还包含一些标识它们可写、可枚举、可配置的特性。在ECMAScript3无法设置这些特性,其属性都是可读可写、可枚举、可配置的根本没有提供API供修改。

    在ECMAScript5中引入了 查询 和 修改这些属性的API。

       这些给库开发者带来好处是:

    1 可以通过这些API给原型对象添加方法,并设置其不可枚举,这让其看起来像内置方法

    2 通过API设置属性不能修改和删除。

       ECMAScript5为了获取和设置这些特性,引入描述对象,而描述对象获取通过 Object.getOwnPropertyDescriptor;

    根据属性类型不同,描述对象返回的内容也不一样:

      数据属性: 值 value 读写 writeable、枚举 enumerable、可配置 configurable 

      存取器属性: set*、get*、枚举 enumerable、可配置 configurable 

    先来了解下 getOwnPropertyDescriptor

      语法:

       /**
          * Gets the own property descriptor of the specified object.
          * An own property descriptor is one that is defined directly on the object and is not inherited from the object's prototype.
          * @param o Object that contains the property.
          * @param p Name of the property.
        */
        getOwnPropertyDescriptor(o: any, p: string): PropertyDescriptor;

    从指定对象,获取自身属性描述对象; 从名字看出来,只能返回自生的属性,而继承而来的属性则只能通过获取其原型对象了

      下面看看具体实例

    var o = {name:"HD"};
    Object.defineProperty(o,"age",{
        configurable:true,
        enumerable:true,
        set:function(age){
            this.age = age;
        },
        get:function(){
            return this.age;
        }
    });
    
    var oDesc_name = Object.getOwnPropertyDescriptor(o,"name");
    
    var oDesc_age = Object.getOwnPropertyDescriptor(o,"age");
    
    var oDesc_money = Object.getOwnPropertyDescriptor(o,"toString");
    
    var none = Object.getOwnPropertyDescriptor(o,"none");
    // { get: [Function: get],set: [Function: set],enumerable: true,configurable: true }
    console.log(oDesc_age);
    // { value: 'HD',writable: true,enumerable: true, configurable: true }
    console.log(oDesc_name);
    
    // undefined console.log(oDesc_money);
    // undefined
    console.log(none); 
     

     

     

       如果要设置或修改描述对象通过 Object.defineProperty 和 Object.defineProperties  前者是单个,后者为批量;这两个区别是后者属性是同时添加的。

    先了解下 Object.defineProperty 语法

     /**
          * Adds a property to an object, or modifies attributes of an existing property.
          * @param o Object on which to add or modify the property. This can be a native JavaScript object (that is, a user-defined object or a built in object) or a DOM object.
          * @param p The property name.
          * @param attributes Descriptor for the property. It can be for a data property or an accessor property.
          */
        defineProperty(o: any, p: string, attributes: PropertyDescriptor): any;
    Object.defineProperty 添加或者修改自有属性,不能修改继承来的属性



     
     1 var o = {name:"HD"};
     2 //添加
     3 Object.defineProperty(o,"custom",{
     4     writable:true,
     5     configurable:true,
     6     enumerable:true,
     7     value:"我是先添加的"
     8 });
     9 console.log(Object.getOwnPropertyDescriptor(o,"custom"));
    10 //修改
    11 Object.defineProperty(o,"custom",{
    12     writable:true,
    13     configurable:true,
    14     enumerable:true,
    15      value:"被修改了 这么神奇"
    16 });
    17 
    18 console.log(Object.getOwnPropertyDescriptor(o,"custom"));
    { value: '我是先添加的',writable: true,enumerable: true,configurable: true }

    { value: '被修改了 这么神奇', writable: true, enumerable: true,configurable: true }

      一种特殊情况,当属性configurable 只能从 true -> false ,当configurable为false时 除了writable可以被修改外 其它特新均不能被更改

     1 var o = {name:"HD"};
     2 //添加
     3 Object.defineProperty(o,"custom",{
     4     writable:true,
     5     configurable:false,
     6     enumerable:true,
     7     value:"我是先添加的"
     8 });
     9 //{ value: '我是先添加的',writable: true,enumerable: true,configurable: false }
    10 console.log(Object.getOwnPropertyDescriptor(o,"custom"));
    11 //修改 configurable
    12 Object.defineProperty(o,"custom",{
    13     writable:true,
    14     configurable:true,  //TypeError: Cannot redefine property: custom
    15     enumerable:true,
    16     value:"被修改了 这么神奇"
    17 });
    18 //修改 enumerable
    19 Object.defineProperty(o,"custom",{
    20     writable:true,
    21     configurable:false,  
    22     enumerable:false,//TypeError: Cannot redefine property: custom
    23     value:"被修改了 这么神奇"
    24 });
    25 //修改 writable
    26 Object.defineProperty(o,"custom",{
    27     writable:false,
    28     configurable:false,  
    29     enumerable:true,
    30     value:"被修改了 这么神奇"
    31 });
    32 
    33 console.log(Object.getOwnPropertyDescriptor(o,"custom"));
    34 
    35 // { value: '被修改了 这么神奇',writable: false,enumerable: true,configurable: false }
    当需要一次添加或修改多个属性时,我们可能里用 defineProperties() 先来看看语法

       /**
          * Adds one or more properties to an object, and/or modifies attributes of existing properties.
          * @param o Object on which to add or modify the properties. This can be a native JavaScript object or a DOM object.
          * @param properties JavaScript object that contains one or more descriptor objects. Each descriptor object describes a data property or an accessor property.
          */
        defineProperties(o: any, properties: PropertyDescriptorMap): any;

      先看看下面实例:

     1 var now = Object.defineProperties({},{
     2     "custom":{
     3         writable:false,
     4         configurable:false,  
     5         enumerable:true,
     6         value:"被修改了 这么神奇"
     7     },
     8     "custom2":{
     9        writable:false,
    10        configurable:false,  
    11        enumerable:true,
    12        value:"被修改了 这么神奇"
    13     }
    14 });
    15 
    16 console.log(now); //{ custom: '被修改了 这么神奇', custom2: '被修改了 这么神奇' }

     在不允许创建或修改的属性来说,如果用 Object.defineProperty()和 Object.defineProperties()会抛出错误!!!!

     问题汇总:

    1     如果对象不可配置,可以编辑已有自有属性,但是不能添加新属性;
    2     当属性configurable 只能从 true -> false ,当configurable为false时 除了writable可以被修改外 其它特新均不能被更改;
    3     当属性不可配置时,数据属性 存取器属性 间不能相互转换;
    4     当数据属性不可写时,修改其值会报错;
  • 相关阅读:
    003 01 Android 零基础入门 01 Java基础语法 01 Java初识 03 Java程序的执行流程
    002 01 Android 零基础入门 01 Java基础语法 01 Java初识 02 Java简介
    001 01 Android 零基础入门 01 Java基础语法 01 Java初识 01 导学
    001 Android Studio 首次编译执行项目过程中遇到的几个常见问题
    Dora.Interception,为.NET Core度身打造的AOP框架 [2]:以约定的方式定义拦截器
    Dora.Interception,为.NET Core度身打造的AOP框架 [1]:更加简练的编程体验
    监视EntityFramework中的sql流转你需要知道的三种方式Log,SqlServerProfile, EFProfile
    轻量级ORM框架——第二篇:Dapper中的一些复杂操作和inner join应该注意的坑
    轻量级ORM框架——第一篇:Dapper快速学习
    CF888G Xor-MST(异或生成树模板)
  • 原文地址:https://www.cnblogs.com/czhyuwj/p/5888620.html
Copyright © 2020-2023  润新知