17Object对象
Object对象
创建对象的三种形式
创建空对象
1
2var obj1 = new Object(null);
var obj2 = new Object(undefined);创建一个与给定值对应类型的对象
1
2var obj3 = new Object(100);
console.log(obj3); //[Number: 100]当以非构造函数形式被调用时,Object 等同于 new Object()。
1
2var obj4 = Object(); //函数调用
var obj5 = new Object(); //构造函数调用
属性描述符
Javascript提供了一个内部数据结构,用于描述对象的值,控制其行为,例如该属性是否可写、是否可配置、是否可修改以及是否可枚举等。这个内部数据结构被称为“属性描述符”。
对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。
数据描述符
键 | 值 | 默认值 |
---|---|---|
value | 该属性对应的值,可以是任何有效的Javascript值(数值,对象,函数等)。 | undefiend |
writable | 当且仅当该属性的writable 为true 时, valueオ能被赋值运算符改変。 | false |
configurable | 当且仅当该属性的configurable 为true 时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除。 | false |
enumerable | 当且仅当该属性的enumerable 为true 时,该属性才能够出现在对象的枚举属性中。 | false |
存取描述符
键 | 值 | 默认值 |
---|---|---|
get | 给属性提供getter 的方法,如果没有getter 则为undefined 。当访问该属性时,该方法会被执行,方法执行时没有参数传入,但是会传人this 对象。 | |
set | 给属性提供setter 的方法,如果没有setter 则为undefined。当属性值修改时,触发执行该方法。该方法将接受唯一参数,即该属性新的参数值 | |
configurable | 当且仅当该属性的configurable 为true 时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除。 | false |
enumerable | 当且仅当该属性的enumerable 为true 时,该属性才能够出现在对象的枚举属性中。 | false |
获取属性描述符
通过Object.getOwnPropertyNames(object,prop)
方法获取属性描述符,其中:
object
表示指定属性对应的目标对象
prop
表示描述符的目标属性名称
返回值
其属性描述符对象
1 | /** |
设置属性描述符
设置属性使用Object.defineProperty(obj,prop,desc)
方法,他的作用有两个:用于定义目标对象的新属性、修改目标对象的已存在属性。其中:
obj
表示目标对象
prop
表示目标对象的目标属性名称
desc
表示属性描述符,必须是对象的格式。
1
2
3{
value: ''
}返回值
返回传递的对象
设置value值
修改一个值
1
2
3
4
5
6var obj = {
// 定义对象的同时定义了该属性以及值(可修改,可删除,可枚举)
name: "张无忌",
};
Object.defineProperty(obj, "name", { value: "周芷若" });
console.log(obj);新增一个值
1
2
3
4Object.defineProperty(obj, "age", {
value: 18,
});
console.log(obj.age); //18
与常规方式的区别
如果使用"对象名.属性名 = 值"
可修改,可删除,可枚举
如果使用
Object.defineProperty()
方法新增属性不可修改命不可删除以及不可枚举
一旦属性的值是不可修改的,执行修改操作:没有语法错误,但修改无效
由图可以得知:用Object.defineProperty()
方法新增属性后,再次修改后输出,值并未发生变化。
设置wriable值
该值为布尔值,默认为false
。表示属性值可否被修改。
修改现有属性
当
writable
为false时,无法修改其属性。1
2
3
4
5
6
7
8
9
10
11
12
13var obj = {
// 定义对象的同时定义了该属性以及值(可修改,可删除,可枚举)
name: "张无忌",
};
// 修改现有属性
Object.defineProperty(obj, "name", {
value: "周芷若",
writable: false,
});
console.log(obj.name); //周芷若
// 修改name属性值
obj.name = "赵敏";
console.log(obj.name); //周芷若新增属性
与修改同理当
writable
为false时,无法修改其属性。为true时可以修改.
设置configurable值
Booleant值,表示目标属性的描述符是否可以被修改。当且仅当该属性的configurable为true时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除.默认为false
设置enumerable值
1 | var obj = { |
以上代码执行结果:
属性描述符也可以设置方法,与上述属性设置一模一样。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28var obj = {
sayMe: function () {
console.log("this is function ");
},
};
var result = Object.getOwnPropertyDescriptor(obj, "sayMe");
console.log(result);
/*
{
value: [Function: sayMe],
writable: true,
enumerable: true,
configurable: true
}
*/
Object.defineProperty(obj, "sayMe", {
value: function () {
console.log("this is new function");
},
writable: false,
});
obj.sayMe(); // this is new function
obj.sayMe = function () {
console.log("这是张无忌");
};
obj.sayMe(); //this is new function
属性描述符的存取器
get
get
当获取或访问当前属性时,会调用此方法。类似数据描述符中的value
get方法在被调用时,不能传递任何参数
get方法在被调用时,允许传递this关键字
- this - 表示当前的目标对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22var obj = {
name: "张无忌",
};
Object.defineProperty(obj, "name", {
// 获取指定的属性
get: function () {
// 当获取或访问当前属性时,会调用此方法
/**
* 类似数据描述符中的value
* get方法在被调用时,不能传递任何参数
* get方法在被调用时,允许传递this关键字
* this - 表示当前的目标对象
*/
// return this;
return "周芷若";
},
});
console.log(obj.name); // 周芷若
// 同样的如果只设置get,那么也是不能修改的。
obj.name = "赵敏";
console.log(obj.name); // 周芷若set
set方法用于定义当前目标函数的修改功能
该方法接收唯一的一个参数
作为当前目标属性的新的值
通过属性修改操作指定新的值
作为形参对应的实参
此方法修改值需借助一个变量,例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18var obj = {
name: "张无忌",
};
var value; //全局变量
Object.defineProperty(obj, "name", {
/**
* set方法用于定义当前目标函数的修改功能
* 该方法接收唯一的一个参数 -> 作为当前目标属性的新的值
* 通过属性修改操作指定新的值 -> 作为形参对应的实参
*
*/
set: function (newvalue) {
console.log("this is set function ");
value = newvalue;
},
});
obj.name = "赵敏";
console.log(obj.name); //赵敏需要注意的是:如果变量没有初始化获取值,那么值是undefined。
1
2
3
4
5
6
7
8
9
10
11var obj = {
name: "张无忌",
};
var value; //全局变量
Object.defineProperty(obj, "name", {
set: function (newvalue) {
console.log("this is set function ");
value = newvalue;
},
});
console.log(obj.name); //undefined
关于get与set的另一种常见写法
1 | var obj = { |
这种写法中,赋值与上方一致,也是定义一个新的变量,然后赋值。此写法结果与用法与上边一致,只是写法不同。
防篡改对象
定义的对象默认在任何时候、任何位置,无论有意义的还是无意义的都可以修改对象的属性或方法。而这些篡改可能会影响对象的内置属性或方法,从而导致对象的正常功能可能无法使用。
Javascript在ES5版本中新増了放置纂改对象的属性或方法的机制,共提供了以下三级保护方式
禁止扩展
禁止为对象扩展新的属性或方法
密封对象
禁止扩展新的属性或方法,禁止配置现有的属性或方法的描述符,仅允许读写属性的值
冻结对象
禁止对对象执行任何修改操作。
禁止扩展
禁止扩展只需要调用Object.preventExtensions(obj)
方法即可,参数就是需要禁止的对象.
一旦设置禁止扩展,那么该对象不可新增属性或方法.
- 使用
obj.name
方法新增不会报错但无效 - 使用
Object.defineProperty
方法新增会报错.
判断对象是否可扩展使用方法Object.isExtensible(obj)
,参数同样是需要判断的对象.
返回一个布尔值,true
表示可被扩展,false
表示不可被扩展.
1 | var obj = {}; |
密封对象
将对象进行密封调用Object.seal(obj)
即可,参数为需要密封的对象.
一旦将对象进行了密封,那么需要注意如下:
- 不能为该对象新增属性或方法
- 不能修改该对象的以下属性或方法的描述符
configurable
enumerable
判断是否是密封对象Object.isSealed(obj)
,参数同样是需要判断的对象.
返回一个布尔值,true
表示被密封了,false
表示没有被密封
1 | var obj = { |
冻结对象
将对象进行密封调用Object.freeze(obj)
即可,参数为需要冻结的对象.
一旦将对象进行了冻结,那么该对象只能使用,不能做任何修改,包括删除
判断是否是密封对象Object.isFrozen(obj)
,参数同样是需要判断的对象.
返回一个布尔值,true
表示被冻结了,false
表示没有被冻结
1 | var obj = { |