zoukankan      html  css  js  c++  java
  • 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     当数据属性不可写时,修改其值会报错;
  • 相关阅读:
    rhel7 编写CMakeList.txt编译运行MySQL官方例子代码
    记录下 rhel 7 安装MySQL 并重置root密码
    杨辉三角 可以不用二维数组的
    一个ACE 架构的 Socket Client
    一个ACE 架构的 C++ Timer
    一个C++版的网络数据包解析策略
    标记下 'net 查壳/脱壳/加壳' 工具
    C++动态加载DLL调用方法
    C# (灰度)加权平均法将图片转换为灰度图
    C# GMap下提供一个高德地图
  • 原文地址:https://www.cnblogs.com/czhyuwj/p/5888620.html
Copyright © 2011-2022 走看看