属性包括名和值,属性名可以包括空字符串在内的任意字符串,但对象中不能存在两个同名的属性。值可以是任意的 JavaScript 值。除了明和值以外,每个属性还有一些相关的值,称之为属性特性。
即便属性是 configurable:false ,我们还是可以 把 writable 的状态由 true 改为 false ,但是无法由 false 改为 true 。
定义属性
在声明变量时可以使用 var ,但是在声明对象属性时不能使用 var 语句。
ECMAScript 5 新增两个静态函数 , 来指定对象定义的属性。
Object.defineProperty
将属性添加到对象(在对象未指明的属性名称时) , 或者修改现有属性(在对象指明属性名称时)。
Object.defineProperty(object, propertyName, descriptors);
Object.defineProperty 返回值为已修改的对象 (writeable 是否可写 、 enumerable 是否可枚举 、 configurable 是否可修改 ) 。
var obj = {};
Object.defineProperty(obj, 'newDataProperty', {
value: 101,
writable: true,
enumerable: true,
configurable: true,
});
obj.newDataProperty = 102;
console.log(obj.newDataProperty); // 102
var obj = {};
Object.defineProperty(obj, 'newAccessorProperty', {
set: function (x) {
this.newaccpropvalue = x * x;
},
get: function () {
return '<h1>' + this.newaccpropvalue + '</h1>';
},
enumerable: true,
configurable: true,
});
obj.newAccessorProperty = 30;
console.log(obj.newAccessorProperty);
// <h1>900</h1>
上例中,使用 Object.defineProperty 函数将访问器将属性添加到用户定义对象 obj 。定义当前为对象的 newAccessorProperty 属性添加新值,设置其值为赋值的平方,而读取该属性时,会以一级标题的形式显示,即输出值为 HTML 字符串。
Object.defineProperties
添加多个或修改多个属性。
Object.defineProperties(object, descriptors);
该参数为一 , 需要用 {} 括起来
var obj = {};
Object.defineProperties(obj, {
newDataProperty: {
value: 101,
writable: true,
configurable: true,
enumerable: true,
},
newAccessorProperty: {
set: function (x) {
this.newAccessorPropValue = x;
},
get: function () {
return this.newAccessorPropValue;
},
enumerable: true,
configurable: true,
},
});
obj.newAccessorPropValue = 10;
console.log(obj.newAccessorPropValue); // 10
上例中,使用 Object.defineProperties 函数将数据属性和访问器添加到用户指定的对象上。使用对象文本创建了 newDataProperty 和 newAccessorPropValue 描述符对象的 descriptors 对象。
<li class="noList indent2">
由于属性没有固定顺序 , 同时也只能枚举自定义属性 . 如果遇到不存在属性 , 返回 undefinedECMAScript 新增了四个 函数来访问对象属性。
Object.getPrototypeOf
Object.getPrototypeOf 可以返回指定对象的原型。
Object.getPrototypeOf(object);
function Pasta(grain, width) {
this.grain = grain;
this.width = width;
}
var spaghetti = new Pasta('wheat', 0.2);
var proto = Object.getPrototypeOf(spaghetti);
console.log(proto === Pasta.prototype); // true
Object.getOwnPropertyNames
Object.getOwnPropertyNames 可以返回指定对象私有属性的名称。私有属性是指直接对该属性定义的属性,而不是从该对象与那行继承的属性。具体用法如下。
Object.getOwnPropertyNames(object);
function Pasta(grain, width, shape) {
this.grain = grain;
this.width = width;
this.shape = shape;
this.toString = function () {
return this.grain + ', ' + this.width + ', ' + this.shape;
};
}
var spaghetti = new Pasta('wheat', 0.2, 'circle');
var arr = Object.getOwnPropertyNames(spaghetti);
console.log(arr); // rain,width,shape,toString
Object.keys
Object.keys 与 Object.getOwnPropertyNames 类似,但是, Object.Keys 仅能返回指定可枚举属性和方法的名称。
Object.keys(object);
参数 object 表示指定的属性,可以是创建的对象或现有 DOM 对象。返回值是一个数组。其中包含可枚举属性和方法的名称。
function Pasta(grain, width, shape) {
this.grain = grain;
this.width = width;
this.shape = shape;
this.toString = function () {
return this.grain + ', ' + this.width + ', ' + this.shape;
};
}
var spaghetti = new Pasta('wheat', 0.2, 'circle');
var arr = Object.keys(spaghetti);
arr.forEach(k => {
console.log(k + '***');
});
// grain *** width *** shape *** toString ***
console.log('');
for (var i in arr) {
console.log(' 这是第 ' + (1 + Number(i)) + '属性,名称: ' + arr[i] + '');
}
// 这是第 1 属性,名称: grain
// 这是第 2 属性,名称: width
// 这是第 3 属性,名称: shape
// 这是第 4 属性,名称: toString
Object.getOwnPropertyDescriptor
Object.getOwnPropertyDescriptor 能够获得指定对象的私有属性的描述。
Object.getOwnPropertyDescriptor(object, propertyName);
参数 object 表示指定的对象, propertyName 表示属性的名称。返回值为属性的描述对象。
var obj = {};
obj.newDataProperty = 'abc';
var descriptor = Object.getOwnPropertyDescriptor(obj, 'newDataProperty');
descriptor.writable = false;
Object.defineProperty(obj, 'newDataProperty', descriptor);
var desc2 = Object.getOwnPropertyDescriptor(obj, 'newDataProperty');
for (var prop in desc2) {
console.log(prop + ': ' + desc2[prop]);
console.log('');
}
/****
* value: abc
* writable: false
* enumerable: true
* configurable: true
*/
与读取对象值操作相同,设置对象属性的值也可以使用使用点运算符和数组操作方法来实现。
var o = {
// 定义对象 x: 1, y: 2
};
o.x = 2; // 设置属性的新值,覆盖原值
o['y'] = 1; // 设置属性的新值,覆盖原值
alert(o['x']); // 返回 2
alert(o.y); // 返回 1
删除属性 delete 运算符直接删除属性 , 枚举失效。
var o = { x: 1 }; // 定义对象
delete o.x;
// 删除对象的属性 x
alert(o.x); // 返回 undefined
当删除对象属性之后,不是将该属性值设置为 undefined ,而是从对象中彻底清除属性。如果使用 for/in 语句枚举对象属性,只能枚举属性值为 undefined 的属性,但是不会枚举已删除的属性。
在 JavaScript 中,方法 ( Method )就是对象属性的一种特殊形式,即值为函数的属性。从功能角度分析,方法就是对象执行特定行为的逻辑块,是与外界交互的动作。
由于函数是一类数据,所以可以赋值给对象属性,于是该属性就是对象的一个方法。
var o = {
x: function () {
// 定义对象方法
alert('Method');
},
};
也可以这样定义方法。
var o = {};
o.x = function () {
// 定义对象方法
alert('Method');
};
使用小括号运算符可以调用对象的方法。
o.x(); // 调用对象的方法
对象内有一个 this 关键字,它总是指向引用调用该方法的对象。
var o = {
x: function () {
// 定义对象的方法
alert(this.y); // 访问当前对象的属性 y 的值
},
};
o.x(); // undefined
var f = o;
f.y = 2;
o.x(); // 2
方法和普通函数一样,可以传入参数,可以设置返回值。
var o = {};
o.x = function (a) {
return a * 10;
};
var f = o.x(5); // 调用方法,设置参数值 5
alert(f); // 返回值 50
构造函数是一类特殊的函数,它能够初始化对象,利用参数初始化 this 关键字所引用对象的 x 和 y 属性值。因此,构造函数就相当于对象的结构模板,利用它可以实例化包含相同属性但属性值不同的对象。
function f() {
// 定义方法
return this.x + this.y;
}
function MyClass(x, y) {
// 定义类
this.x = x;
this.y = y;
this.add = f; //将方法封装在类中,这样每一个实例都拥有该方法
}
var o = new MyClass(10, 20); // 实例化类,并初始化参数值
alert(o.add()); // 调用方法,返回值 30
function f() {
// 定义方法
return this.x + this.y;
}
function MyClass() {
// 定义类
this.x = arguments[0];
this.y = arguments[1];
this.add = f; // 将方法封装在类中,这样每一个实例都拥有该方法
}
var o = new MyClass(10, 20); // 实例化类,并初始化参数值
alert(o.add()); // 调用方法,返回值 30
ECMAScript 5 新增 3 个函数用来设置对象属性的特性: Object.seal 、 Object.freeze 和 Object.preventExtensions 。这 3 个函数用来保护指定属性,防止修改现有属性,或阻止添加新属性。但是,作用略有不同。
Object.seal(object);
Object.freeze(object);
Object.preventExtensions(object);
函数 | 不可添加新属性 | 不可设置特性 | 不可修改属性值 |
---|---|---|---|
Object.preventExtensions | Y | N | N |
Object.seal | Y | Y | N |
Object.freeze | Y | Y | Y |
在上述 3 个函数用法相同,都有一个参数,用来指定要限制的对象。
var obj = { pasta: 'spaghetti', length: 10 };
Object.preventExtensions(obj);
obj.newProp = 50;
obj.pasta = 50;
console.log(obj.newProp); // undefined
console.log(obj.pasta); // 50
上例,使用 Object.preventExtensions 函数阻止 obj 添加新的属性。下例,将函数由 Object.preventExtensions 改为 Object.freeze 将阻止修改属性。
var obj = { pasta: 'spaghetti', length: 10 };
Object.freeze(obj);
obj.newProp = 50;
obj.pasta = 50;
console.log(obj.newProp); // undefined
console.log(obj.pasta); // spaghetti
为确定属性的特性, ECMAScript 5 新增了 3 个函数来检测,即 Object.isSealed 、 Object.isFrozen 和 Object.Extensible 。
var obj = { pasta: 'spaghetti', length: 10 };
if (!Object.isFrozen(obj)) {
obj.pasta = 50;
}
Object.freeze(obj);
console.log(obj.pasta); // 50
var obj = { pasta: 'spaghetti', length: 10 };
Object.freeze(obj);
if (!Object.isFrozen(obj)) {
obj.pasta = 50;
}
console.log(obj.pasta); // spaghetti