静态方法:Object.defineProperty();Object.defineProperties();

Object.defineProperty(obj, prop, descriptor)

  • 参数1: 需要添加属性的对象 (一个对象)

  • 参数2: 要添加属性名 (字符串)

  • 参数3: 描述符. 对要添加的属性设置一些特性 (一个对象)

  • 返回值: 参数1传递过去那个对象.


面向对象高级知识加强

一、对象的属性的特性

JavaScript中的属性一共分两种:

  1. 数据属性。 比如我我们以前接触到的属性都属于数据属性。
  2. 访问器属性。访问器属性不包含数据值。包含一堆setter和getter函数。

1.1 数据属性

比如我们以前自定义的属性都是数据属性。数据属性包含一个数据值的位置,在这个位置可以读取和写入值。

有4个特性来描述每一个数据属性:

  • [[Configurable]]:表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。像我们以前自定义的属性,它们的这个特性默认值为 true
  • [[Enumerable]]:表示能否通过 for-in 循环返回属性。我们以前自定义的属性,它们的这个特性默认值为 true。
  • [[Writable]]:表示能否修改属性值。我们以前自定义的属性,默认值都是true
  • [[value]]:包含这个属性的值。读取属性的时候从这个地方读,写入属性的值的时候会写入到这个值中。这个特性的默认值是undefined

看下面的代码:

var p = {
  name = "lisi"
}

在上面的代码中创建了一个对象p,p有一个属性name,则name属性就有了4个上面说的特性。[[Configurable]]、[[Enumerable]]、[[Writable]]这个3个特性都是默认值。

[[value]]的值被修改为 'lisi'。 以后不管去获取值或者修改name属性的的值都是从这个对这个特性进行操作的。

要修改数据属性的特性的值,则创建对象的属性的时候就不能像以前那样去创建。必须使用ES5提供的心的方法:Object.defineProperty()

Object.definePropery() :这个方法接受三个参数

  1. 属性所在的对象。 也就是你要把属性添加到那个对象上。
  2. 属性名。 要添加的属性的名字
  3. 描述符对象。 就是对这个属性的四个特性进行描述的对象。
<script type="text/javascript">
  "use strict"
  var person = {
  };
  Object.defineProperty(person, "name", {
    writable : false,
    value:"lisi"
  })
  console.log(person.name);
  //因为name属性是不可修改的(只读),所以此处不会起作用。
  //非严格模式没有任何反应,严格模式下会抛出异常。
  person.name = "zhangsan";
  console.log(person.name);
</script>

类似的规则也适用其他其他特性。

<script type="text/javascript">

var a = {};
Object.defineProperty(a, "name", {
    value : "李四",  // 要添加的属性的属性值. 默认值是undefined
    enumerable : true,   // 是否可枚举,表示使用for in是否可以访问到.  默认是false.
    writable : true,  // 是否可写. 表示是否可以修改这个属性的值  默认是false
    configurable : false  // 是否可配置  表示是否可以更改描述符中的值或是否可以删除这个属性的值 默认是false
});
</script>

注意:在调用Object.definePropery()方法时,如果不指定,则configurable、enumerable 和 writable特性的默认值都是 false。

绝大部分情况下,我们都不需要使用这个种方式定义属性。

1.2 访问器属性

访问器属性不包含数据值;它们包含一对儿 getter 和 setter 函数(不过,这两个函数都不是必需的)。

在读取访问器属性时,会调用 getter 函数,这个函数 返回有效的值;

在写入访问器属性时,会调用setter 函数并传入新值,这个函数 决定如何处理数据。

访问器属性有如下 4 个特性:

  • [[Configurable]]:表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为数据属性。对于直接在对象上定义的属性,这个特性的默认值为true。
  • [[Enumerable]]:表示能否通过 for-in 循环返回属性。对于直接在对象上定义的属性,这 个特性的默认值为 true。
  • [[Get]]:在读取属性时调用的函数。默认值为 undefined。
  • [[Set]]:在写入属性时调用的函数。默认值为 undefined。

注意:访问器属性不能直接定义,只能通过Object.definePropery()方法定义。

<script type="text/javascript">
    var book = {
        //这个属性用下划线开头表示一种约定:不要直接访问这个属性,用方法访问。
        _year: 2004,
        edition: 1
    }
    //定义一个访问器属性.他的configurable 是false。 enumerable也是false
    Object.defineProperty(book, "year", {
          //访问属性year的时候会调用这个方法
        get: function () {
            return this._year;
        },
         //修改访问器属性的时候会调用这个方法
        set: function (newValue) {
            if (newValue > 2004) {
                this._year = newValue;
                this.edition += newValue - 2004;
            }
        }
    });
    console.log(book.year)  // 2004
    book.year = 2005;
    console.log(book.edition); //2
</script>

[[get]]、[[set]]不一定同时设定,如果只设定[[get]]则是只读,只设定[[set]]则是只写。

1.3 一次性定义多个属性

Object.definePropery()一次性只能定义一个。

Object.defineProperties() 可以同时定义多个属性。

只需要两个参数:

参数1:要添加属性的对象

参数2:对象的属性名做键,属性的特性组成的对象做值,组成的对象。

看下面的代码:

<script type="text/javascript">
    var p = {};
    Object.defineProperties(p,{
          //name属性。
        name : {
            enumerable:true,
            configurable:false,
            writable:false,
            value:"凤姐"
        },
          //age属性。
        age:{
            enumerable : true,
            configurable:true,
            get:function () {
                return 18;
            },
            set : function () {
                console.log("想修改我的年龄没门")
            }
        }
    });


</script>

1.4 读取属性的特性的值

使用Object.getOwnPropertyDescriptor(参数1, 参数2)方法。这个方法接收两个参数。

参数1:属性所在的对象

参数2:属性名称。

返回值:一个对象。 如果是访问器属性,这个对象的属性有 configurable、enumerable、get 和 set;如果是数据属性,这个对象的属性有 configurable、enumerable、writable 和 value。

<script type="text/javascript">
    var p = {};
    Object.defineProperties(p,{
        name : {
            enumerable:true,
            configurable:false,
            writable:false,
            value:"凤姐"
        },
        age:{
            enumerable : true,
            configurable:true,
            get:function () {
                return 18;
            },
            set : function () {
                console.log("想修改我的年龄没门")
            }
        }
    });
    var pd = Object.getOwnPropertyDescriptor(p, "name");
    console.log(pd);

</script>



Copyright © 李振超 2018 all right reserved,powered by Gitbook
该文件最后修订时间: 2018-10-18 03:22:12

results matching ""

    No results matching ""