var myObj = { key: value // ... };//字面量
var myObj = new Object(); //new myObj.key = value;
String,Number,Boolean,Object,Function,Array,Date,RegExp,Error
在使用string
等创建的字面量形式时,js会隐试转换成其对应的内置对象,null
和 undefined
没有对应的构造形式,Date
只有构造,没有字面量形式
var myObject = { a: 2 }; myObject.a; // 2 myObject["a"]; // 2
. 操作符要求属性名满足标识符的命名规范,而 [".."] 语法 可以接受任意 UTF-8/Unicode 字符串作为属性名。在对象中,属性名永远都是字符串。如果你使用 string(字面量)以外的其他值作为属性 名,那它首先会被转换为一个字符串。即使是数字也不例外
ES6 增加了可计算属性名[prefix + "bar"]
var prefix = "foo"; var myObject = { [prefix + "bar"]:"hello", [prefix + "baz"]: "world" }; myObject["foobar"]; // hello myObject["foobaz"]; // world
function anotherFunction() { /*..*/ } var anotherObject = { c: true }; var anotherArray = []; var myObject = { a: 2, b: anotherObject, // 引用 c: anotherArray, // 引用 d: anotherFunction }; anotherArray.push( anotherObject, myObject );
以上代码myObject中的b,c只是引用了anotherObject,anotherArray,相当于b指向anotherObject,anotherObject指向c,而b并没有直接指向c,只是做了一层浅拷贝。
可以通过JSON实现一个深拷贝,JSON.stringify( someObj )
将对象someObj生成一个JSON字符串,但这种方法只适用于对象内的属性可以被JSON序列化的情况
var newObj = JSON.parse( JSON.stringify( someObj ) );
ES6 Object.assign(..)
可以实现对象的浅拷贝
var myObject = { a:2 }; Object.getOwnPropertyDescriptor( myObject, "a" ); // { // value: 2, // writable: true, 可写 // enumerable: true,可枚举 // configurable: true 可配置 // }
Object.getOwnPropertyDescriptor
获取对象属性的描述,
var myObject = {}; Object.defineProperty( myObject, "a", { value: 2, writable: true, configurable: true, enumerable: true } ); myObject.a; // 2
Writable
决定是否可以修改属性的值。
Configurable
Enumerable
控制属性是否会出现在对象的属性枚举中
var myObject = {}; Object.defineProperty( myObject, "FAVORITE_NUMBER", { value: 42, writable: false, configurable: false } );
结合 writable:false
和 configurable:false
就可以创建一个常量属性(不可修改、 重定义或者删除)
var myObject = { a:2 }; Object.preventExtensions( myObject ); myObject.b = 3; myObject.b; // undefined
Object.preventExtensions( myObject );
禁止一个对象myObject
添加新属性并且保留已有属性
Object.seal(..) 会创建一个“密封”的对象,这个方法实际上会在一个现有对象上调用 Object.preventExtensions(..) 并把所有现有属性标记为 configurable:false。
Object.freeze(..) 会创建一个冻结对象,这个方法实际上会在一个现有对象上调用 Object.seal(..) 并把所有“数据访问”属性标记为 writable:false,这样就无法修改它们的值。
var myObject = { a: 2};myObject.a; // 2
在语言规范中,myObject.a 在 myObject 上实际上是实现了 [[Get]] 操作,对象默认的内置 [[Get]] 操作首先在对象中查找是否有名称相同的属性, 如果找到就会返回这个属性的值,反之遍历可能存在的 [[Prototype]] 链上是否有属性a,没有[[Get]] 操作会返回值 undefined。
注意,这种方法和访问变量时是不一样的。如果你引用了一个当前词法作用域中不存在的变量,并不会像对象属性一样返回 undefined,而是会抛出一个 ReferenceError 异常
var myObject = { a: undefined }; myObject.a; // undefined myObject.b; // undefined
仅根据返回值无法判断出到底变量的值为 undefined 还是变量不存在
[[Put]] 被触发时,如果已经存在这个属性,[[Put]] 算法大致会检查下面这些内容。
属性是否是访问描述符
,如果是并且存在setter就调用setter。
属性的数据描述符中writable是否是false?如果是,在非严格模式下静默失败,在严格模式下抛出 TypeError 异常。
如果都不是,将该值设置为属性的值。
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
不管是对象文字语法中的get a() { .. },还是defineProperty(..)中的显式定义,二者 都会在对象中创建一个不包含值的属性,对于这个属性的访问会自动调用一个隐藏函数, 它的返回值会被当作属性访问的返回值
var myObject = { // 给 a 定义一个 getter get a() { return this._a_; }, // 给 a 定义一个 setter set a(val) { this._a_ = val * 2; } }; myObject.a = 2; myObject.a; // 4
setter 会覆盖单个属性默认的 [Put]操作。通常来说 getter 和 setter 是成对出现的
var myObject = { a:2 }; ("a" in myObject); // true ("b" in myObject); // false myObject.hasOwnProperty( "a" ); // true myObject.hasOwnProperty( "b" ); // false
in 操作符会检查属性是否在对象及其 [[Prototype]] 原型链中,hasOwnProperty(..) 只会检查属性是否在 myObject 对象中,不会检查 [[Prototype]] 链。
var myObject = { }; Object.defineProperty( myObject, "a", // 让 a 像普通属性一样可以枚举 { enumerable: true, value: 2 } ); Object.defineProperty( myObject, "b", // 让b不可枚举 { enumerable: false, value: 3 } ); myObject.b; // 3 ("b" in myObject); // true myObject.hasOwnProperty( "b" ); // true // ....... for (var k in myObject) { console.log( k, myObject[k] ); } myObject.propertyIsEnumerable( "a" ); // true myObject.propertyIsEnumerable( "b" ); // false Object.keys( myObject ); // ["a"] Object.getOwnPropertyNames( myObject ); // ["a", "b"] // "a" 2
propertyIsEnumerable(..) 会检查给定的属性名是否直接存在于对象中(而不是在原型链 上)并且满足 enumerable:true。
对象中的函数并不属于对象本身而只是保存了对函数引用的指针,指向函数实际的地址。
对象本身并不带有迭代器,所以要使用for...of遍历对象时需要内置一个迭代器,而数组内部自带了迭代器可以直接使用for...of遍历。
对象查找属性时先会寻扎当前对象是否有该属性,没有则在该对象的原型链上查找,没找到会返回undefined,所以当获取一个属性值返回undefined时并不能确定该属性是否不存在
for ... in...用在对象上,用在数组上不仅会包含所有数值索引,还会包含所有可枚举属性,数组用for循环
有 的 对 象 可 能 没 有 连 接 到 Object.prototype( 通 过 Object. create(null) 来创建)Object.prototype.hasOwnProperty. call(myObject,"a")
【你不知道的javaScript 上卷 笔记6】javaScript中的对象相关内容
原文:https://www.cnblogs.com/seny-33/p/12210403.html