logo头像

孙宇

重拾JavaScript(Object对象)

一、概念

  • 对象是一个抽象的概念, 可以将其简单的理解为: 数据集或功能集(对象就是可以拥有属性和方法的一个集合).

二、语法

  • 对象可以通过两种形式定义,声明(文字)形式和构造形式.
  1. 声明式
    var myObj = { key: value};
  2. 构造式
    var myObj = new Object(); myObj.key = value;

三、JavaScript内置对象

  • String
  • Number
  • Boolean
  • Object
  • Function
  • Array
  • Date
  • RegExp
  • Error

四、内容

  • .操作符(属性访问) [] 操作符(键访问)
1
2
3
var myObject = { a: 2};
myObject.a; // 2 .操作符(属性访问)
myObject["a"]; // 2 [] 操作符(键访问)

(1)、可计算属性名

1
2
3
4
5
6
7
var prefix = "foo";
var myObject = {
[prefix + "bar"]:"hello",
[prefix + "baz"]: "world"
};
myObject["foobar"]; // hello
myObject["foobaz"]; // world

(2)、属性和方法

1
2
3
4
5
6
function Obj() {
this.name = 'sy'; //属性
this.say = function() { //方法
console.log('my name is ' + this.name)
}
}

(3)、属性描述符

  • Object.getOwnPropertyDescriptor() 方法返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)
  1. 语法
    Object.getOwnPropertyDescriptor(obj, prop)
    
  2. 参数
    obj需要查找的目标对象 prop目标对象内属性名称
    
  3. 返回值

    如果指定的属性存在于对象上,则返回其属性描述符对象(property descriptor),否则返回 undefined。
    
  4. 实例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var myObject = { a:2};
    Object.getOwnPropertyDescriptor( myObject, "a" );
    // {
    // value: 2,
    // writable: true,
    // enumerable: true,
    // con gurable: true
    // }
    Object.getOwnPropertyDescriptor( myObject, "b" );
    //undefined。
  • Object.defineProperties() 方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象。
  1. 语法
    Object.defineProperties(obj, props)
    
  2. 参数
    obj在其上定义或修改属性的对象。
    props
    要定义其可枚举属性或修改的属性描述符的对象。对象中存在的属性描述符主要有两种:数据描述符和访问器描述符(更多详情,请参阅Object.defineProperty())。描述符具有以下键:
    configurable
    true 当且仅当该属性描述符的类型可以被改变并且该属性可以从对应对象中删除。
    默认为 false
    enumerable
    true 当且仅当在枚举相应对象上的属性时该属性显现。
    默认为 false
    value
    与属性关联的值。可以是任何有效的JavaScript值(数字,对象,函数等)。
    默认为 undefined.
    writable
    true当且仅当与该属性相关联的值可以用assignment operator改变时。
    默认为 false
    get
    作为该属性的 getter 函数,如果没有 getter 则为undefined。函数返回值将被用作属性的值。
    默认为 undefined
    set
    作为属性的 setter 函数,如果没有 setter 则为undefined。函数将仅接受参数赋值给该属性的新值。
    默认为 undefined
    
  3. 返回值

    传递给函数的对象。
    
  4. 举例

1
2
3
4
5
6
7
8
9
10
1. 在创建普通属性时属性描述符会使用默认值,我们也可以使用 Object.defineProperty(..) 
来添加一个新属性或者修改一个已有属性(如果它是 configurable)并对特性进行设置。
var myObject = {};
Object.defineProperty( myObject, "a", {
value: 2,
writable: true,
configurable: true,
enumerable: true
});
myObject.a; // 2
1
2
3
4
5
6
7
8
9
10
11
12
2. Writable
writable 决定是否可以修改属性的值。
var myObject = {};
Object.defineProperty( myObject, "a", {
value: 2,
writable: false, // 不可写!
configurable: true,
enumerable: true
});
myObject.a = 3;
myObject.a; // 2
使用严格模式会TypeError (TypeError 错误表示我们无法修改一个不可写的属性。)
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
3. Configurable
只要属性是可配置的,就可以使用 defineProperty(..) 方法来修改属性描述符:
var myObject = { a:2};
myObject.a = 3;
myObject.a; // 3
Object.defineProperty( myObject, "a", {
value: 4,
writable: true,
configurable: false, // 不可配置!
enumerable: true
});
myObject.a; // 4
myObject.a = 5;
myObject.a; // 5
Object.defineProperty( myObject, "a", {
value: 6,
writable: true,
configurable: true,
enumerable: true
}); // TypeError
- 最后一个 defineProperty(..) 会产生一个 TypeError 错误,不管是不是处于严格模式,
尝试修改一个不可配置的属性描述符都会出错。注意:如你所见,
把 configurable 修改成 false 是单向操作,无法撤销!
- 要注意有一个小小的例外:即便属性是 configurable:false,
我们还是可以 把 writable 的状态由 true 改为 false,但是无法由 false 改为 true。

var myObject = { a:2};
myObject.a; // 2
delete myObject.a;
myObject.a; // undefined
Object.defineProperty( myObject, "a", {
value: 2,
writable: true,
configurable: false,
enumerable: true
} );
myObject.a; // 2
delete myObject.a;
myObject.a; // 2

因为不可配置 所以delete(静默)失败。
1
2
3
4. Enumerable
是否可以对象的属性枚举
比如说 for..in 循环。如果把 enumerable 设置成 false,这个属性就不会出现在枚举中
1
2
3
4
5
5. Getter和Setter(对象默认的 [[Put]] 和 [[Get]] 操作分别可以控制属性值的设置和获取。)
当你给一个属性定义 getter、setter 或者两者都有时,
这个属性会被定义为“访问描述 符”(和“数据描述符”相对)。
对于访问描述符来说,JavaScript 会忽略它们的 value 和 writable 特性,
取而代之的是关心 set 和 get(还有 configurable 和 enumerable)特性。

(4)、不变性

  • 对象常量
    1
    2
    3
    4
    5
    6
    7
    8
    var myObject = {};
    Object.defineProperty( myObject, "FAVORITE_NUMBER", {
    value: 42,
    writable: false,
    configurable: false
    });

    - 禁止扩展 (禁止一个对象添加新属性并且保留已有属性)

var myObject = { a:2};
Object.preventExtensions( myObject );
myObject.b = 3;
myObject.b; // undefined

1
2
3
4
- 密封 Object.seal(..) 会创建一个“密封”的对象,这个方法实际上会在一个现有对象上调用 Object.preventExtensions(..) 并把所有现有属性标记为 configurable:false。
所以,密封之后不仅不能添加新属性,也不能重新配置或者删除任何现有属性(虽然可以 修改属性的值)。

- 冻结 Object.freeze(..) 会创建一个冻结对象,这个方法实际上会在一个现有对象上调用 Object.seal(..) 并把所有“数据访问”属性标记为 writable:false,这样就无法修改它们 的值。

(5)、存在性

  • in 操作符会检查属性是否在对象及其 [[Prototype]] 原型链中
  • hasOwnProperty(..) 只会检查属性是否在 myObject 对象中,不会检查 [[Prototype]] 链
  • propertyIsEnumerable(..) 会检查给定的属性名是否直接存在于对象中(而不是在原型链 上)并且满足 enumerable:true。
  • Object.keys(..) 会返回一个数组,包含所有可枚举属性,Object.getOwnPropertyNames(..) 会返回一个数组,包含所有属性,无论它们是否可枚举。
  • for..in 循环可以用来遍历对象的可枚举属性列表(包括 [[Prototype]] 链)。