第三章 属性高级

一、属性描述符

1.获取对应属性的描述符

属性描述符:属性的特征;也叫元属性;修饰属性的属性

Object.getOwnPropertyDescriptor(obj,"name"); 第一个参数:对应的对象 第二个参数:对应对象的属性


  var obj={
  name:"wql",
  age:38,
  wife:"lss"
 
}
  var res=Object.getOwnPropertyDescriptor(obj,"wife");
  console.log(res)
//res是一个对象
{
    1. configurable: true
    2. enumerable: true
    3. value: "lss"
    4. writable: true
    5. __proto__: Object
}

 

2.为对象新增或修改属性

var obj={
    name:"snw"
};
Object.defineProperty(obj,"age",{
    value:18,
    writable:true,
    configurable:true,
    emumerable:true
});
console.log(obj); //Object {name: "snw", age: 18}
console.log(obj.age);//18
 
 
 
 
属性描述符的默认值都是false

 

3.writable(可写的)

writable决定是否可以修改属性的值
 
当writable为false时,对应的属性的值是无法修改的。
 // writable为false 时 configurable一般也为false 在默认情况下: 继续修改的话会静默失败 在严格模式下: 会报错

var obj={
name:"Lebron",
age:33,
team:"湖人"
}
//obj.team="骑士"; 位置在这儿能被修改
Object.defineProperty(obj,"team",{
writable:false
})
obj.team="热火";
console.log(obj);

 

4.configurable(可配置的)

configurable来决定属性是否可以配置
可配置:属性能否重新定义 属性能否删除 当configurable为false时,对应的属性是无法重新定义的,无法删除的。但该对象是还可以继续添加属性的。 默认情况下
进行重新定义会报错
进行删除会静默失败 注意一个小小的例外: 当configurable为false时,writable可以进行重新定义,但只满足由writable:
true ==> writable:false

   var obj={
       name:"zyy",
       age:20,
       hobby:"eat"
     }
     Object.defineProperty(obj,"hobby",{
      //value:"play",
        writable:true,
        configurable:false,
        enumerable:false
    })

     delete obj.hobby;
     console.log(obj);

 

5.enumerable

//enumerable可枚举:控制了属性的可枚举权限
//可枚举:能否出现在对象的for in 循环中



var obj={
    name:"zyy",
    age:26,
    behavior:"play basketball"
}
Object.defineProperty(obj,"behavior2",{
    value:"eat",
    enumerable:false
})

for(var item in obj){
  console.log(item);
}

6.严格模式

<!--
    严格模式的语法比较严谨
        没有通过var定义的变量 在严格模式底下就会报错
        this的指向
            普通调用时 如果是严格模式 那this指向undefined
   严格模式的管理范围:作用域

   在属性描述符writable为flase的情况下 对属性值进行修改 就会报错不会静默失败
   在属性描述符configurable为flase的情况下 对属性进行删除 就会报错不会静默失败

-->
<script>
    function test() {
        "use strict"
        inner();
        function inner() {
            console.log(this)
        }
    }
    
    (function () {
        "use strict"
        test()
    })()

 

7.属性的指定方式

/*属性的指定方式:
       1. 字面量初始化的时候直接通过 键值对的形式指定
                属性描述符的默认值基本都是true
       2. 通过对象点的形式来指定
                属性描述符的默认值基本都是true
       3. 原始的指定形式的方式
`               属性描述符的默认值基本都是false
               value:undefined
        4. var a = "a"; 给window添加的属性
                configurable: false
                enumerable: true
                writable: true
        5.    b="b";给window添加的属性
            属性描述符的默认值基本都是true
   */

    var a = "a";
    b="b";
    console.log(Object.getOwnPropertyDescriptor(window,"a"))
    console.log(Object.getOwnPropertyDescriptor(window,"b"))
    delete  a;
    delete  b;
    console.log(a);
    console.log(b);

 

8.存在性检查

var obj={
        a:undefined,
        wife:{
            name:"xxx"
        }
    };
    console.log(obj.a);

    //in关键字 会影响对象的直接属性 也访问原型链  可是不访问对象的深层属性
    console.log("a" in obj)
    console.log("b" in obj)
    console.log("toString" in obj)
    console.log("name" in obj,"------")

    //在js中所有的方法都是 浅不变形 的;只会影响对象的直接属性 不访问原型链 也不访问对象的深层属性
    console.log(obj.hasOwnProperty("a"));
    console.log(obj.hasOwnProperty("b"));
    console.log(obj.hasOwnProperty("toString"));
    console.log(obj.hasOwnProperty("name"));

    var res = Object.getOwnPropertyNames(obj);
    console.log(res);

 

9.访问描述符(get&&set)

    // 属性描述符 : 属性的特征  属性的属性
    // 数据描述符 : 具有writable 和 value属性描述符 的属性!
    // 访问描述符 : 具有set 和 get属性描述符 的属性!

    var obj={
        get age(){
        return obj.__age__;
         },
       set age(val){
            if (val > 150){
               val =150;
       }else if(val < 0){
               val =0;
         }


      obj.__age__=val;
       }
   }


obj.age=33;
console.log(obj.age);

 

二、对象不变性

1.对象常量属性

将属性的writable和configurable设置为false

      var MathCopy = {};
      Object.defineProperty(MathCopy,"PI",{
           value:3.141592654,
           writable:false,
           configurable:false,
           enumerable:true
      })
       MathCopy.PI=1;
      console.log(MathCopy.PI)



 

2.禁止对象扩展

由于属性描述符是对属性的管理
 
所以想禁止对象扩展不能使用属性描述符来控制,而是需要调用Object.preventExtensions(obj);
 
参数:要求禁止扩展的对象
 
 
默认情况下
    为对象添加新的属性会静默失败
严格模式底下
    报错
 
 
注意:禁止对象扩展只是禁止了对象去扩展属性,
而之前的属性是可以进行重新定义或者删除的,
属性值也是可以修改的

3.密封对象

在禁止对象扩展(Object.preventExtensions(obj);的基础上把现有属性的configurable都调整为false
  
调用Object.seal(obj)密封一个对象
  
密封之后禁止了对象去扩展属性,原有的属性不可以进行重新定义或者删除,但属性值是可以修改的

 var obj = {
        a:"a",
        b:'b'
    };
    Object.seal(obj);


       delete obj.a;
       obj.c="c";
       obj.a="aa";
    console.log(obj);

输出:{a: "aa", b: "b"}   没有被删除,也没有添加c

 

4.冻结对象(浅)


    在密封对象(Object.seal(obj))的基础上把现有属性的writable都调整为false

    调用Object.freeze(obj)密封一个对象

   冻结之后禁止了对象去扩展属性,原有的属性不可以进行重新定义或者删除,属性值不可以进行修改




var
obj = { a:"a", b:'b' }; Object.freeze(obj); delete obj.a; obj.c="c"; obj.a="aa"; console.log(obj);

 

5.冻结对象(深)

<script>
    var obj = {
        name: "zyy",
        age: 20,
        hobby: {
            No1: "playball",
            No2: "eat",
            No3: "sleep"
        }
    }
   
    function deep(obj) {
        var keys = Object.getOwnPropertyNames(obj);
        keys.forEach(function (key) {
            var val = obj[key]
            if (Object.prototype.toString.call(val) === "[object Object]") {
                deep(val)
            }

        });
        return Object.freeze(obj)

    }
deep(obj);
obj.hobby.No1="watch";
console.log(obj)


</script>

三、属性查找和设置

1.基本规则

/* 数据描述符
        configurable: true
        enumerable: true
        writable: true
*/

    // 查找: 先在对象的直接属性中找 找到了就返回 找不到上原型链 整体原型链都没有 返回 undefined
    // 设置: 只影响对象的直接属性

 

2.完整的规则(查找)

 // [[Get]]:代表的属性查找的算法
        // [[Get]]:
        //     1.在对象中查找是否具有相同名称的属性,如果找到,就会返回这个属性的值。
        //     2.如果没有找到,则遍历原型链
        //     3.无论如何都没找到,返回undefined
        //     4.访问描述符具体看get方法的逻辑

 

3.完整的规则(设置)

/*
    [[Put]]:代表的属性设置的算法

    obj.a="a";
    [[put]]:
        1.
            如果属性直接存在于对象中 不在原型链上
            找到直接存在于对象中的属性
            -数据描述符(没有setter/getter)
                直接修改对象中的属性(注意writbale的值)
            -访问描述符
                直接调用set方法
        4.
            如果属性直接存在于对象中  也在原型链上
            找到直接存在于对象中的属性
            -数据描述符(没有setter/getter)
                直接修改对象中的属性(注意writbale的值)
            -访问描述符
                直接调用set方法
        2.
            如果属性不直接存在于对象中也不在原型链上
            在对象的直接属性中添加一个属性(数据描述符)
                value:"a"
                writable:true
                configurable:true
                enumerable:true

    3.
        如果属性不直接存在于对象中  在原型链上
             ①.该属性是数据描述符(没有setter/getter)
                -writbale为true
                    直接在对象中添加一个属性,我们称之为屏蔽属性
(√)(√)(√)(√)-writbale为false
                    报错,不会生成屏蔽属性

(√)(√)(√)(√) ②.该属性是访问描述符
                调用set,不会生成屏蔽属性
    */

    // Object.prototype.a="a";
    Object.defineProperty(Object.prototype,"a",{
        set:function(val){

        }
    })
    var obj={};
    obj.a="aaaa";
    console.log(obj,Object.prototype)
</script>

 

object

静态方法
    Object.create()
    Object.defineProperty()
    Object.getOwnPropertyDescriptor()
    Object.getOwnPropertyNames()
    Object.preventExtensions()
    Object.seal()
    Object.freeze()
    Object.keys()
实例方法
    Object.prototype.toString()
    Object.prototype.valueOf()
    Object.prototype.propertyIsEnumerable()

 

posted @ 2018-12-23 12:17  _俗  阅读(125)  评论(0编辑  收藏  举报