1. 什么是对象
对象是无序属性的集合
创建自定义对象最简单的方式就是以字面量的形式创建对象(或创建一个Object实例),然后再为它添加属性和方法,如下所示:
var person = {
name: "Nicholas",
age: 29,
sayHi: function() {
console.log(this.name);
}
}
但是我们需要定义对象中的某个属性能否修改,能够重写等属性,那我们应该如何定义
2. 内置属性—数据属性
Object.defineProperty()方法介绍(摘自MDN)
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象
语法:Object.defineProperty(obj, prop, descriptor)
参数:
(1)obj:需要被操作的目标对象
(2)prop:目标对象需要定义或修改的属性的名称
(3)descriptor:将被定义或修改的属性的描述符
返回:被传递给函数的对象
2.1 configurable属性
是否可以删除目标属性或是否可以再次修改属性的特性(writable, configurable, enumerable)。默认为false
设置为true可以被删除或可以重新设置特性;
设置为false,不能被可以被删除或不可以重新设置特性,只能将writable
从true
置为false
一旦把属性定义为不可配置的,就不能再把它便会可配置的,这一点很重要
主要起到数据的保护作用,决定了目标属性是否可以使用delete删除,是否可以再次设置特性
//-----------------测试目标属性是否能被删除------------------------
var obj = {}
// 第一种情况:configurable设置为true,可以被删除。
Object.defineProperty(obj, "newKey", {
value: "hello",
configurable: true
});
// 删除属性
delete obj.newKey;
console.log( obj.newKey ); //undefined
// 第二种情况:configurable设置为false,不能被删除。
Object.defineProperty(obj, "newKey", {
value: "hello",
configurable: false
});
// 删除属性
delete obj.newKey;
console.log( obj.newKey ); //hello
//-----------------测试是否可以再次修改特性------------------------
var obj = {}
//第一种情况:configurable设置为false,不能再次修改特性。
Object.defineProperty(obj, "newKey", {
value: "hello",
writable: false,
enumerable: false,
configurable: false
});
//重新修改特性
Object.defineProperty(obj, "newKey", {
value: "hello",
writable: true,
enumerable: true,
configurable: true
});
console.log( obj.newKey ); //报错:Uncaught TypeError: Cannot redefine property: newKey
//第二种情况:configurable设置为true,可以再次修改特性。
Object.defineProperty(obj, "newKey", {
value: "hello",
writable: false,
enumerable: false,
configurable: true
});
//重新修改特性
Object.defineProperty(obj, "newKey", {
value: "hello",
writable: true,
enumerable: true,
configurable: true
});
console.log( obj.newKey ); //hello
2.2 enumerable 属性
此属性是否可以被枚举(使用for...in或Object.keys())默认为false
设置为true可以被枚举;设置为false,不能被枚举
var obj = {}
// 第一种情况:enumerable设置为false,不能被枚举。
Object.defineProperty(obj, "newKey", {
value: "hello",
writable: false,
enumerable: false
});
// 枚举对象的属性
for( var attr in obj ){
console.log( attr ); // undefined
}
// 第二种情况:enumerable设置为true,可以被枚举。
Object.defineProperty(obj, "newKey", {
value: "hello",
writable: false,
enumerable: true
});
// 枚举对象的属性
for( var attr in obj ){
console.log( attr ); //newKey
}
2.3 value 属性
属性对应的值,可以是任意类型的值,默认为undefined;
var obj = {}
// 第一种情况:不设置value属性
Object.defineProperty(obj, "key", {});
console.log( obj.key ); //undefined
// 第二种情况:设置value属性
Object.defineProperty(obj, "key", {
value: "hello"
});
console.log( obj.key ); //hello
// 同字面定义的数据值对应
2.4 writable 属性
属性的值是否可以被重写。默认为false
设置为true可以被重写;设置为false,不能被重写
var obj = {}
// 第一种情况:writable设置为false,不能重写。
Object.defineProperty(obj, "newKey", {
value: "hello",
writable: false
});
// 更改newKey的值
obj.newKey = "change value";
console.log( obj.newKey ); //hello
// 第二种情况:writable设置为true,可以重写
Object.defineProperty(obj, "newKey", {
value: "hello",
writable: true
});
// 更改newKey的值
obj.newKey = "change value";
console.log( obj.newKey ); //change value
2.5 默认值理解(重点)
在调用 Object.defineProperty 方法给对象添加属性时,如果不指定,configurable、enumerable、writable这些值都为默认的false
==> 使用 Object.getOwnPropertyDescriptor() 方法来查看对象的内置属性
var obj = {};
// 第一种情况:使用 Object.defineProperty() 定义属性
Object.defineProperty(obj, 'key', {
value: "hello"
});
Object.getOwnPropertyDescriptor(obj, 'key');
// {value: "hello", writable: false, enumerable: false, configurable: false}
// 第二种情况:字面量方式
obj.key = "hello";
Object.getOwnPropertyDescriptor(obj, 'key');
// {value: "hello", writable: true, enumerable: true, configurable: true}
2.6 数据属性总结
- configurable: 目标属性是否可以被删除或是否可以再次修改特性 true | false
- enumerable: 目标属性是否可以被枚举。true | false
- value: 设置属性的值 undefined
- writable: 值是否可以重写。true | false
3. 内置对象—访问器属性
Object.getOwnPropertyDescriptor()方法介绍(摘自MDN)
Object.getOwnPropertyDescriptor() 方法返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)
语法:Object.getOwnPropertyDescriptor(obj, prop)
参数:
(1)obj:需要被操作的目标对象
(2)prop:目标对象内属性名称(String类型)
返回:如果指定的属性存在于对象上,则返回其属性描述符对象(property descriptor),否则返回 undefined
3.1 configurable 属性
参照数据属性中的configurable属性
3.2 enumerable 属性
参照数据属性中的enumerable属性
3.3 get 方法
在读取属性是调用的函数,默认值为undefined
var obj = {}, value = "hello";
Object.defineProperty(obj, 'key', {
get: function() {
console.log("获取obj.key的值上下文");
return value;
}
});
console.log(obj.key); // "获取obj.key的值上下文" hello
obj.key = "new value";
console.log(obj.key); // "获取obj.key的值上下文" hello
3.4 set 方法
在写入属性时调用的函数,默认值为undefined
// 一般不会单独为属性设置set而不设置get
var obj = {}, value = "hello";
Object.defineProperty(obj, 'key', {
set: function(val) {
console.log("设置obj.key的值上下文");
}
});
obj.key = "new value"; // "获取obj.key的值上下文"
console.log(obj.key); // undefined
不一定非要同时指定getter和setter。只指定getter意味着属性是不能写,尝试写入属性会被忽略。在严格模式下,尝试写入只指定getter函数的属性会抛出错误。类似的,只指定setter函数的属性也不能读,否则在非严格模式下会返回undefined,而在严格模式下会抛出错误。
var book = {
_year: 2004,
edition: 1 };
Object.defineProperty(book, "year", {
get: function() {
return this._year;
},
set: function(newValue) {
if (newValue > 2004) {
this._year = newValue;
this.edition += newValue - 2004;
}
}
});
book.year = 2005; alert(book.edition); //2
使用访问器属性的常见方式,即设置一个属性的值会导致其他属性发生变化
3.5 数据和视图联动(重点)
给对象o定义新的属性b,并且定义属性b的get和set方法,当o.b的时候会调用b属性的get方法,给b属性赋值的时候,会调用set方法,这就是修改数据的时候,视图会自动更新的关键前端获取数据后,需要根据数据操作dom,视图变化后,需要修改不少代码,有没有方法将数据和dom操作隔离,看一个例子
<!-- 显示用户信息的html模版 -->
<div>
<p>你好,<span id='nickName'></span></p>
<div id="introduce"></div>
</div>
// 视图控制器
var userInfo = {};
Object.defineProperty(userInfo, "nickName", {
get: function(){
return document.getElementById('nickName').innerHTML;
},
set: function(nick){
document.getElementById('nickName').innerHTML = nick;
}
});
Object.defineProperty(userInfo, "introduce", {
get: function(){
return document.getElementById('introduce').innerHTML;
},
set: function(introduce){
document.getElementById('introduce').innerHTML = introduce;
}
});
// 数据
// todo 获取用户信息的代码
// ....
userInfo.nickName = "xxx";
userInfo.introduce = "我是xxx,我来自云南,..."
访问器属性是实现MVVM框架的核心原理哦~
4. 定义多个属性
Object.defineProperties() 方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象
语法:Object.defineProperties(obj, props)
参数:
(1)obj:在其上定义或修改属性的对象
(2)props:要定义其可枚举属性或修改的属性描述符的对象。对象中存在的属性描述符主要有数据描述符和访问器描述符两种
返回:传递给函数的对象
var obj = {};
Object.defineProperties(obj, {
'property1': {
value: true,
writable: true
},
'property2': {
value: 'Hello',
writable: false
}
// etc. etc.
});
参考:
Javascript中的Object.defineProperty
MDN Object.defineProperty
MDN Object.getOwnPropertyDescriptor
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。