sailei1 / blog

1 stars 0 forks source link

你不知道的JS 对象 笔记 #71

Closed sailei1 closed 4 years ago

sailei1 commented 4 years ago

简单基本类型 string boolean number null undefined symbol 引用类型 object

null 和 undefined 没有对应的构造形式,它们只有文字形式。相反,Date 只有构造,没有 文字形式。

在对象中,属性名永远都是字符串, ES6 增加了可计算属性名。

浅复制 复制值 不复制引用对象,只复制引用连接 深复制 复制值 也复制引用对象 Object.assign(..) 浅复制 JSON.parse( JSON.stringify( someObj ) ) 深复制 适用于部分情况

属性描述符

var myObject = {};
 Object.defineProperty( myObject, "a", {
        value: 2,
        writable: true, 
        configurable: true, 
        enumerable: true
     } );
 myObject.a; // 2
//writable=false 变量值不可修改 严格模式下会报错(TypeError)
//Configurable=false  
configurable 修改成false 是单向操作,无法撤销!
即便属性是 configurable:false,我们还是可以把 writable 的状态由 true 改为 false,但是无法由 false 改为 true。
对象属性key 禁止删除

// Enumerable=false 控制属性是否会出现对象的属性枚举中, 比如 for .. in 循环

对象常量 结合 writable:false 和 configurable:false 就可以创建一个真正的常量属性(不可修改、重定义或者删除) 禁止扩展 如果你想禁止一个对象添加新属性并且保留已有属性,可以使用 Object.preventExtensions(..)

var myObject = {
       a:2    
   };
     Object.preventExtensions( myObject );
     myObject.b = 3;
     myObject.b; // undefined
//在非严格模式下,创建属性 b 会静默失败。在严格模式下,将会抛出 TypeError 错误。

密封 Object.seal(..) 会创建一个“密封”的对象,这个方法实际上会在一个现有对象上调用Object.preventExtensions(..) 并把所有现有属性标记为 configurable:false。 所以,密封之后不仅不能添加新属性,也不能重新配置或者删除任何现有属性(虽然可以修改属性的值)。 冻结 Object.freeze(..) 会创建一个冻结对象,这个方法实际上会在一个现有对象上调用Object.seal(..) 并把所有“数据访问”属性标记为 writable:false,这样就无法修改它们的值。 这个方法是你可以应用在对象上的级别最高的不可变性,它会禁止对于对象本身及其任意直接属性的修改(不过就像我们之前说过的,这个对象引用的其他对象是不受影响的)。

setter getter

var myObject = {
// 给 a 定义一个 getter 
get a() {
     return 2; 
     }
};
Object.defineProperty(myObject, // 目标对象
   "b", // 属性名
   {
   // 给 b 设置一个 getter
    get: function(){ return this.a * 2 },
    // 确保 b 会出现在对象的属性列表中
    enumerable: true
   });
myObject.a; // 2
myObject.b; // 4
//hasOwnProperty
var myObject = { a:2};

myObject.hasOwnProperty( "a" ); // true
myObject.hasOwnProperty( "b" ); // false

Object.prototype.hasOwnProperty.call(myObject,"a")//true

检查属性枚举

var myObject = { };
     Object.defineProperty( myObject,
          "a",
       // 让 a 像普通属性一样可以枚举 
        { enumerable: true, value: 2 }
     );
     Object.defineProperty(myObject,
             "b",
         // 让 b 不可枚举
           { enumerable: false, value: 3 }
);
myObject.propertyIsEnumerable( "a" ); // true
myObject.propertyIsEnumerable( "b" ); // false
Object.keys( myObject ); // ["a"]
Object.getOwnPropertyNames( myObject ); // ["a", "b"]
//propertyIsEnumerable(..) 会检查给定的属性名是否直接存在于对象中(而不是在原型链上)并且满足 enumerable:true。
//Object.keys(..) 会返回一个数组,包含所有可枚举属性
// Object.getOwnPropertyNames(..)会返回一个数组,包含所有属性,无论它们是否可枚举。

遍历 for .. of

var myArray = [ 1, 2, 3 ];
for (var v of myArray) { 
   console.log( v );
}
//for..of 循环首先会向被访问对象请求一个迭代器对象,然后通过调用迭代器对象的next() 方法来遍历所有返回值。

var myObject = {
                a: 2,
                b: 3};

for(var k in myObject){console.log(k);}
//a 
//b

Object.defineProperty( myObject, Symbol.iterator,
         {enumerable: false,
        writable: false,
        configurable: true,
        value: function() { 
         var o = this;
         var idx = 0;
         var ks = Object.keys( o );
         return {next: function() { return {
                         value: o[ks[idx++]],
                         done: (idx > ks.length)
                     };}
                     };
                     }
        });

// 用 for..of 遍历 myObject 
for (var v of myObject) {
 console.log( v );
}
//2 
//3