本系列随笔是本人的学习笔记,初学阶段难免会有理解不当之处,错误之处恳请指正。另:转载请注明出处。
简介
JavaScript 中,对象可以看做是“属性”的集合(这里的“属性”不仅是属性名,而是一个键/值对,即属性名和属性值)。
对象的创建方式
JavaScript 中可以用以下三种方式创建对象:
- 直接使用字面值对象(看起来同JSON格式);
- 使用 new 运算符创建(new 后面跟一个构造函数调用,JavaScript 中没有“类”的概念,对象是通过构造函数创建而来的)
- 使用 Object.create() 方法,其第一个参数指定对象的原型对象(可以理解为parent对象),第二个参数为可选参数,用以指定属性相关特性(同Object.defineProperties()的第二个参数)
示例:
var a = {}; // #1,字面值创建方式,创建一个空对象 var b = { x: 1, y: 2 }; // #2,字面值创建方式,创建一个非空对象 var c = new Object(); // #3,通过 new 运算符创建,创建一个空对象,同 #1 var d = new Date(); // #4,通过 new 运算符创建,创建一个日期对象 var e = Object.create(Object.prototype); // #5,创建一个空对象,同 #1 和 #3 var f = Object.create(b); // #6,创建一个继承自 b 的对象 f.x = 3; // 并不会影响父对象 b 中的属性值 console.log(b); // { x: 1, y: 2 } console.log(f); // { x: 3 },这里虽然没有输出 y 属性,但是通过 f.y 能访问 y 属性值 console.log(f.y); // 2
属性的特性
JavaScript 中,对象可以看做是“属性”的集合(这里的“属性”不仅包括属性名,还包括属性值和一组特性)。
属性的特性可以表明该属性是否为只读属性、是否可枚举、是否可配置等。
查看一个属性的特性,可以使用 Object.getOwnPropertyDescriptor() 方法,例如(下面的示例查看对象 o 中的 x 属于性的特性):
var o = { x: 1, y: 2 }; console.log(Object.getOwnPropertyDescriptor(o, "x")); // {value: 1, writable: true, enumerable: true, configurable: true}
修改某个属性的特性,可以使用 Object.defineProperty() 方法,例如:
var o = { x: 1, y: 2 }; console.log(Object.getOwnPropertyDescriptor(o, "x")); // {value: 1, writable: true, enumerable: true, configurable: true} Object.defineProperty(o, 'x', { writable: false }); // 这里可以同时修改多个特性,也可以单独修改某个特性 console.log(Object.getOwnPropertyDescriptor(o, "x")); // {value: 1, writable: false, enumerable: true, configurable: true}
如果想要同时修改多个属性,请参考:Object.defineProperties()。
如果想要在创建对象的时候指定属性特性,可通过 Object.create() 方法的第二个参数进行设置。
设置属性的 getter 和 setter
属性值可以是一个简单的数据,这样的属性称为“数据属性”。
与之相对的,JavaScript 还支持为属性设置读写方法(getter和setter),这样的属性称为“存取器属性”。如果设置了 getter 表明该属性可读,如果设置了 setter 表明该属性可写,例如:
"use strict" var c = { x: 3, y: 4, get r() { // r 设置了 getter 和 setter,所以它是个可读、可写属性 return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2)); }, set r(v) { var ratio = v / this.r; this.x = this.x * ratio; this.y = this.y * ratio; }, get s() { return Math.PI * Math.pow(this.r, 2); } // s 只设置了 getter,所以它是个只读属性 }; console.log(c.x, c.y, c.r, c.s); // 3 4 5 78.53981633974483 c.r = 10; console.log(c.x, c.y, c.r, c.s); // 6 8 10 314.1592653589793 c.s = 20; // Uncaught TypeError: Cannot set property s of #<Object> which has only a getter,只有在严格模式下,这里才会报错
注意:
- “数据属性”包含 value、writable、enumerable、configurable 四个特性;
- 而“存取器属性”因为 其值 和 writable 分别根据是否设置了 getter 和 setter 决定可否访问,因此它没有 value、writable 这两个特性,示例:
console.log(Object.getOwnPropertyDescriptor(c, "x")); // {value: 3, writable: true, enumerable: true, configurable: true}
console.log(Object.getOwnPropertyDescriptor(c, "r")); // {enumerable: true, configurable: true, get: ƒ, set: ƒ} console.log(Object.getOwnPropertyDescriptor(c, "s")); // {set: undefined, enumerable: true, configurable: true, get: ƒ}
in 与 hasOwnProperty() 的区别
in 可以检测对象的自有属性和继承属性,而 hasOwnProperty() 仅可用于检测对象的自有属性,例如:
var p = { x: 1, y: 2 }; var c = Object.create(p); c.z = 3; console.log("x" in c); // true console.log("z" in c); // true console.log(c.hasOwnProperty("x")); // false console.log(c.hasOwnProperty("z")); // true
未完待续。