属性特征

1. 简介

JS 的对象是一组无序属性的集合。那么对于这组无序属性来说,拥有哪些特性呢?ECMAScrip5 中定义了属性的这些特性,但这些特性是为了实现 JS 引擎用的,在 JS 中无法直接来访问它们。为了表示这些特性是内部值,这些特性被放在两对方括号中。例如 [[Enumerable]]。

ECMAScript 中有两种属性:数据属性和访问器属性。

2. 数据属性和访问器属性

2.1 数据属性

数据属性包含一个数据值的位置,在这个位置可以读取和写入值。数据属性有 4 个描述其行为的特性。

  1. 可配置性 [[Configurable]] : 表示能否通过 delete 删除属性,能否修改属性特性,能否把数据属性修改为访问器属性。
  2. 可枚举性 [[Enumerable]]:表示能否通过 for-in 循环返回属性。
  3. 可写入性 [[Writable]]:表示能否修改属性值。
  4. 属性值 [[Value]]:表示属性值。

2.2 访问器属性

访问器属性不包含数据值,而是包含一对 getter 和 setter 函数(这两个函数非必须)。在读取访问器属性时,调用 getter 函数,在写入访问器属性时,调用 setter 函数。访问器属性由 4 个特性:

  1. 可配置性 [[Configurable]]:表示能否通过 delete 删除属性,能否修改属性特性,能否把访问器属性修改为数据属性。
  2. 可枚举性 [[Enumerable]]:表示能否通过 for-in 循环返回属性。
  3. 读取属性函数 [[Get]]:在读取属性时调用的函数。
  4. 写入属性函数 [[Set]]:在写入属性时调用的函数。

3. 属性描述符概述

对于数据属性和访问器属性,其特性值是无法直接访问的。要对这些特性值进行修改,可以使用 ECMAScript5 提供的 Object.defineProperty() 方法。该方法接受三个参数:属性所在对象,属性名字和一个描述符对象。

属性所在对象,属性名字很好理解。那么属性描述符对象呢?它其实是和属性的特性一一对应,只不过没有了两对中括号,我们可以通过 ECMAScript5 提供的一些方法来修改描述符对象。另外,可以用 Object.getOwnPropertyDescriptor() 方法,取得指定对象指定属性的描述符。这个方法接收两个参数:属性所在对象,属性名字。更多的方法我们会在文章后面详细介绍。

3.1 数据属性描述符对象

数据属性描述符对象有 4 个属性。

  1. 可配置性 configurable : 表示能否通过 delete 删除属性,能否修改属性特性,能否把数据属性修改为访问器属性。
  2. 可枚举性 enumerable:表示能否通过 for-in 循环返回属性。
  3. 可写入性 writable:表示能否修改属性值。
  4. 属性值 value:表示属性值。

3.2 访问器属性描述符对象

访问器属性描述符对象有 4 个属性。

  1. 可配置性 configurable:表示能否通过 delete 删除属性,能否修改属性特性,能否把访问器属性修改为数据属性。
  2. 可枚举性 enumerable:表示能否通过 for-in 循环返回属性。
  3. 读取属性方法 get:在读取属性值时调用的函数。
  4. 写入属性方法 set:在写入属性值时调用的函数。

4. 属性描述符详解

4.1 数据属性描述符对象

4.1.1 属性值 value

对于数据属性,我们通过 value 来定义和获取其属性值。如下:

// demo4.1.1
var obj = {};

// 指定属性a,其value外的所有描述符属性都为true
Object.defineProperty(obj, ‘a‘, {
    value: 1,
    writable: true,
    enumerable: true,
    configurable: true
});

console.log(Object.getOwnPropertyDescriptor(obj, ‘a‘));  // {value: 1, writable: true, enumerable: true, configurable: true}

console.log(obj.a);  // 1

可以看到,读取 obj 的属性 a 的值时,即为获取其描述符对象的 value 属性值。

4.1.2 可写入性 writable

如果需要改变 a 的值,可以有如下两种办法:

// demo4.1.2-1
// 接demo4.1.1

// 方法1,直接赋值
obj.a = 2;

console.log(Object.getOwnPropertyDescriptor(obj, ‘a‘));  // {value: 2, writable: true, enumerable: true, configurable: true}
console.log(obj.a);  // 2

// 方法2,Object.defineProperty
Object.defineProperty(obj, ‘a‘, {
    value: 3,
    writable: true,
    enumerable: true,
    configurable: true
});

console.log(Object.getOwnPropertyDescriptor(obj, ‘a‘));  // {value: 3, writable: true, enumerable: true, configurable: true}
console.log(obj.a);  // 3

我们发现打印出来的值就是 a 的 value 值,再一次证明了 obj 的属性 a 的值即为其描述符对象的 value 属性值。但如果我们修改 writable 的值为 false 呢?看如下代码:

// demo4.1.2-2
// 接demo4.1.2-1
Object.defineProperty(obj, ‘a‘, {
    value: 1,
    writable: false,
    enumerable: true,
    configurable: true
});
console.log(Object.getOwnPropertyDescriptor(obj, ‘a‘));  // {value: 1, writable: false, enumerable: true, configurable: true}
console.log(obj.a);  // 1

// 尝试修改a的值
// 方法1,直接赋值
obj.a = 2;

console.log(Object.getOwnPropertyDescriptor(obj, ‘a‘));  // {value: 1, writable: true, enumerable: true, configurable: true}
console.log(obj.a);  // 1

// 方法2,Object.defineProperty
Object.defineProperty(obj, ‘a‘, {
    value: 3,
    writable: false,
    enumerable: true,
    configurable: true
});

console.log(Object.getOwnPropertyDescriptor(obj, ‘a‘));  // {value: 3, writable: false, enumerable: true, configurable: true}
console.log(obj.a);  // 3

可以看到,当 writable 的值为 false 以后,无法再对属性 value 直接使用赋值修改,但是仍然可以用 Object.defineProperty() 方法进行修改。

4.1.3 可配置性 configurable

还记得我们在 4.1.2 使用了两种方法修改 a 的值,但是当 writable 为 false 以后,直接赋值的方法失效了,但是 Object.defineProperty() 方法仍然有效,那我们来看一下 configurable 设置为 false 以后会是什么情况呢?

// demo4.1.3-1
var obj = {};

Object.defineProperty(obj, ‘a‘, {
    value: 1,
    writable: true,
    enumerable: true,
    configurable: false
});

console.log(Object.getOwnPropertyDescriptor(obj, ‘a‘));  // {value: 1, writable: true, enumerable: true, configurable: false}

console.log(obj.a);  // 1

// 尝试修改a的值
// 方法1,直接赋值可以成功
obj.a = 2;

console.log(Object.getOwnPropertyDescriptor(obj, ‘a‘));  // {value: 2, writable: true, enumerable: true, configurable: false}
console.log(obj.a);  // 2

// 方法2,Object.defineProperty可以成功
Object.defineProperty(obj, ‘a‘, {
    value: 3,
    writable: true,
    enumerable: true,
    configurable: false
});

console.log(Object.getOwnPropertyDescriptor(obj, ‘a‘));  // {value: 3, writable: true, enumerable: true, configurable: false}
console.log(obj.a);  // 3

我们发现 writable: true,configurable: false 时两种方法都可以修改 value 值。那么我们看看此时若将 writable 设置为 false 会有什么情况:

// demo4.1.3-2
// 接demo4.1.3-1
// 第一次修改,修改前writable: true
Object.defineProperty(obj, ‘a‘, {
    value: 4,
    writable: false,
    enumerable: true,
    configurable: false
});

console.log(Object.getOwnPropertyDescriptor(obj, ‘a‘));  // {value: 4, writable: false, enumerable: true, configurable: false}
console.log(obj.a);  // 4

// 第二次修改,修改前writable: false
Object.defineProperty(obj, ‘a‘, {
    value: 5,
    writable: false,
    enumerable: true,
    configurable: false
});

console.log(Object.getOwnPropertyDescriptor(obj, ‘a‘));
console.log(obj.a);

结果第二次修改,会有如下报错:

我们发现 writable: false,configurable: false 时两种方法都不可以再修改 value 值。
此时,我们尝试将 writable 修改回 true:

// demo4.1.3-3
// 接demo4.1.3-2
Object.defineProperty(obj, ‘a‘, {
    value: 4,
    writable: true,
    enumerable: true,
    configurable: false
});

console.log(Object.getOwnPropertyDescriptor(obj, ‘a‘));
console.log(obj.a);

发现此时报图 demo4.1.3-2 所示错误,已经无法将 writable: false 修改回 writable: true。
而对于 configurable: false 时是否可以修改 enumerable 呢?来看一下:

// demo4.1.3-4
var obj = {};

Object.defineProperty(obj, ‘a‘, {
    value: 1,
    writable: true,
    enumerable: true,
    configurable: false
});

Object.defineProperty(obj, ‘a‘, {
    value: 1,
    writable: true,
    enumerable: false,
    configurable: false
});

而对于 configurable: false 时是否可以修改 configurable 呢?来看一下:

// demo4.1.3-5
var obj = {};

Object.defineProperty(obj, ‘a‘, {
    value: 1,
    writable: true,
    enumerable: true,
    configurable: false
});

Object.defineProperty(obj, ‘a‘, {
    value: 1,
    writable: true,
    enumerable: true,
    configurable: true
});

发现此时报图 demo4.1.3-2 所示错误,无法修改 configurable 属性。
然后我们再看一下是否能删除整个属性值。

// demo4.1.3-6
var obj = {};

Object.defineProperty(obj, ‘a‘, {
    value: 1,
    writable: true,
    enumerable: true,
    configurable: true
});

console.log(Object.getOwnPropertyDescriptor(obj, ‘a‘));  // {value: 1, writable: true, enumerable: true, configurable: true}
console.log(obj.a);  // 1
delete(obj.a);
console.log(obj.a);  // undefined

Object.defineProperty(obj, ‘a‘, {
    value: 1,
    writable: true,
    enumerable: true,
    configurable: false
});

console.log(Object.getOwnPropertyDescriptor(obj, ‘a‘));  // {value: 1, writable: true, enumerable: true, configurable: false}
console.log(obj.a);  // 1
delete(obj.a);
console.log(obj.a);  // 1

可以看出,configurable: false 时,无法删除属性值。
总结以上信息,可配置性 configurable 有如下特征:

  1. configurable 值为 true 时,可以删除属性值;configurable 值为为 false 时,不能删除属性值;
  2. configurable 值为 true 时,可以修改任意描述符属性值;configurable 值为 false 时,修改规则遵循 3,4,5。
  3. configurable 值为为 false 时,如果 writable 值为 true,可以使用 Object.defineProperty()方法改变 value 值;configurable 值为为 false 时,如果 writable 值为 false,不能使用 Object.defineProperty() 方法改变 value 值;
  4. configurable 值为 false 时,如果 writable 值为 true,可以修改其为 false;configurable 值为 false 时,如果 writable 值为 false,不能修改其为 true;
  5. configurable 值为 false 时,除 3,4 两种情况,不可修改描述符属性值。
4.1.4 可枚举性 enumerable

该属性值控制的是属性是否会出现在对象的属性枚举中,比如说 for…in 循环(会遍历对象自身的和继承的可枚举属性)或者 Object.keys() 方法(返回对象自身的所有可枚举属性)。

// demo4.1.4
var obj = {};

// 指定属性a,其value外的所有描述符属性都为true
Object.defineProperty(obj, ‘a‘, {
    value: 1,
    writable: true,
    enumerable: true,
    configurable: true
});
// 指定属性b,其value外的所有描述符属性都为true
Object.defineProperty(obj, ‘b‘, {
    value: 2,
    writable: true,
    enumerable: true,
    configurable: true
});

console.log(Object.keys(obj));  // ["a", "b"]
for (let key in obj) {
    console.log(`${key}: ${obj[key]}`);
}  // a: 1 b:2

//将属性b的描述符对象的可枚举属性更改为false
Object.defineProperty(obj, ‘b‘, {
    enumerable: false,
});
console.log(Object.keys(obj));  // ["a"]
for (let key in obj) {
    console.log(`${key}: ${obj[key]}`);
}  // a: 1

可以看到,enumerable 控制了属性的可枚举性。

4.2 访问器属性描述符对象

4.2.1 get 方法

读取属性值时所调用的方法,会触发隐藏的 getter 操作。** 设置了 get 或 set 方法的属性,会自动变成访问器属性,不再从 value 读取属性值。** 用 Object.getOwnPropertyDescriptor 方法也不再返回 value 和 writable。

// demo4.2.1-1
var obj = {};

Object.defineProperty(obj, ‘a‘, {
    // 属性a的值由get函数返回
    get: function() {
        return 1;
    }
});
console.log(Object.getOwnPropertyDescriptor(obj, ‘a‘));  // {get: ƒ, set: undefined, enumerable: false, configurable: false}
console.log(obj.a);  // 1

另外,你也可以在对象字面量定义中直接指定属性的 get 方法来触发 getter 操作。

// demo4.2.1-2
var obj = {
    get a() {
        return 1;
    }
};

console.log(Object.getOwnPropertyDescriptor(obj, ‘a‘));  // {get: ƒ, set: undefined, enumerable: false, configurable: false}
console.log(obj.a);  // 1
4.2.2 set 方法

设置属性值时所调用的方法,会触发隐藏的 setter 操作。** 设置了 get 或 set 方法的属性,会自动变成访问器属性,不再从 value 读取属性值。** 用 Object.getOwnPropertyDescriptor 方法也不再返回 value 和 writable。

// demo 4.2.2-1
var obj = {
    _a: 1,
    _doubleA: 2
};
Object.defineProperty(obj, ‘a‘, {
    get: function() {
        return this._a;
    },
    // set方法能接收用户传入的值,并利用该值对对象的任一属性做操作
    set: function(val) {
        this._a = val;
        this._doubleA = 2 * this._a;
    }
});

console.log(Object.getOwnPropertyDescriptor(obj, ‘a‘));  // {get: ƒ, set: ƒ, enumerable: false, configurable: false}
console.log(Object.getOwnPropertyDescriptor(obj, ‘_a‘));  // {value: 1, writable: true, enumerable: true, configurable: true}
console.log(Object.getOwnPropertyDescriptor(obj, ‘_doubleA‘)); // {value: 2, writable: true, enumerable: true, configurable: true}
console.log(obj.a);  // 1
console.log(obj._a); // 1
console.log(obj._doubleA); // 2

obj.a = 2;

console.log(Object.getOwnPropertyDescriptor(obj, ‘_a‘));  // {value: 2, writable: true, enumerable: true, configurable: true}
console.log(Object.getOwnPropertyDescriptor(obj, ‘_doubleA‘)); // {value: 4, writable: true, enumerable: true, configurable: true}
console.log(obj.a);  // 2
console.log(obj._a); // 2
console.log(obj._doubleA); // 4

另外,你也可以在对象字面量定义中直接指定属性的 set 方法来触发 setter 操作。

// demo 4.2.2-2
var obj = {
    _a: 1,
    _doubleA: 2,
    get a() {
        return this._a;
    },
    set a(val){
        this._a = val;
        this._doubleA = 2 * this._a;
    }
};

console.log(Object.getOwnPropertyDescriptor(obj, ‘a‘));  // {get: ƒ, set: ƒ, enumerable: false, configurable: false}
console.log(Object.getOwnPropertyDescriptor(obj, ‘_a‘));  // {value: 1, writable: true, enumerable: true, configurable: true}
console.log(Object.getOwnPropertyDescriptor(obj, ‘_doubleA‘)); // {value: 2, writable: true, enumerable: true, configurable: true}
console.log(obj.a);  // 1
console.log(obj._a); // 1
console.log(obj._doubleA); // 2

obj.a = 2;

console.log(Object.getOwnPropertyDescriptor(obj, ‘_a‘));  // {value: 2, writable: true, enumerable: true, configurable: true}
console.log(Object.getOwnPropertyDescriptor(obj, ‘_doubleA‘)); // {value: 4, writable: true, enumerable: true, configurable: true}
console.log(obj.a);  // 2
console.log(obj._a); // 2
console.log(obj._doubleA); // 4
4.2.3 可配置性 configurable

和在数据属性描述符对象中功能一样。表示能否通过 delete 删除属性,能否修改属性特性,能否把访问器属性修改为数据属性。

4.2.4 可枚举性 enumerable

和在数据属性描述符对象中功能一样。表示能否通过 for-in 循环返回属性。

5. 不同方法创建对象属性以后的属性描述符默认值

5.1 对象字面量指定属性

// demo5.1
// 普通的对象字面量定义方法,是数据属性,writable,enumerable和configurable默认都是true
var obj1 = {
    a: 1
};
// 对象字面量中指定某个属性的get方法或者set方法,是访问器属性,enumerable和configurable默认是true,get或者set仅指定一者的情况下另一个为undefined
var obj2 = {
    get a() {
        return 1;
    }
}
console.log(Object.getOwnPropertyDescriptor(obj1, ‘a‘)); // {value: 1, writable: true, enumerable: true, configurable: true}
console.log(Object.getOwnPropertyDescriptor(obj2, ‘a‘)); // {get: ƒ, set: undefined, enumerable: true, configurable: true}

5.2 构造函数

// demo 5.2
// 构造函数定义方法,是数据属性,writable,enumerable和configurable默认都是true
function Obj() {
    this.a = 1;
}
var obj = new Obj;
console.log(Object.getOwnPropertyDescriptor(obj, ‘a‘)); // {value: 1, writable: true, enumerable: true, configurable: true}

5.3 Object.create() 方法

Object.create() 方法其实是在一个空对象的原形上添加属性并返回该对象。

// demo 5.3
var obj = Object.create({a:1});
// 返回一个空对象
//  console.log(obj); // {}
console.log(Object.getOwnPropertyDescriptor(obj, ‘a‘));  // undefined
// 返回的对象,其原形上面该属性为数据属性,writable,enumerable和configurable默认都是true
console.log(Object.getOwnPropertyDescriptor(obj.__proto__, ‘a‘)); // {value: 1, writable: true, enumerable: true, configurable: true}

5.4 Object.defineProperty()方法和 Object.defineProperties() 方法

// demo 5.4
var obj = {};

// Object.defineProperty()方法指定的属性,如果描述符对象为空,默认是数据属性,value默认是undefined,writable,enumerable和configurable默认都是false
Object.defineProperty(obj, ‘a‘, {
});
console.log(Object.getOwnPropertyDescriptor(obj, ‘a‘));  // {value: undefined, writable: false, enumerable: false, configurable: false}

// Object.defineProperty()方法指定的数据属性,value默认是undefined,writable,enumerable和configurable默认都是false
Object.defineProperty(obj, ‘b‘, {
    value: 1
});
console.log(Object.getOwnPropertyDescriptor(obj, ‘b‘));  // {value: 1, writable: false, enumerable: false, configurable: false}

// Object.defineProperty()方法指定的访问器属性,set或者get未指定默认是undefined,enumerable和configurable默认都是false
Object.defineProperty(obj, ‘c‘, {
    get: function() {
        return 1;
    }
});
console.log(Object.getOwnPropertyDescriptor(obj, ‘c‘));  // {get: ƒ, set: undefined, enumerable: false, configurable: false}

// 用Object.defineProperties()方法同时定义的多个属性,与Object.defineProperty()方法定义的表现相同
Object.defineProperties(obj, {
  ‘d‘: {
    value: true,
    writable: true
  },
  ‘e‘: {
    value: ‘Hello‘,
    writable: false
  }
  // etc. etc.
});
console.log(Object.getOwnPropertyDescriptor(obj, ‘d‘));  // {value: true, writable: true, enumerable: false, configurable: false}
console.log(Object.getOwnPropertyDescriptor(obj, ‘e‘));  // {value: "Hello", writable: false, enumerable: false, configurable: false}

6. 数据属性和访问器属性的区别和使用场景

到这里,你应该会有这样的疑惑,为什么要有两种属性呢,它们有什么关系,又有哪些应用场景呢?

其实,我们从第 5 节内容可以看到,如果不使用 Object.defineProperty()或者 Object.defineProperties() 以及指定 get 和 set 等特殊方法定义的对象属性,默认都是数据属性。这其实是由我们的需求场景来定的。

  1. 在一般情况下,我们关注的只是属性的赋值与取值,也就是仅仅关注数据属性的 value。
  2. 有只读需求的情况,即如果不允许直接以赋值方式更改属性值,就需要用到数据属性的 writable 特性,将其设置为 false。当然如果此时 configurable 若为 true,仍然允许使用 Object.defineProperty() 方法来更改属性值。如果要完全返回固定值,且不允许任何方式修改,可以设置 configurable 为 false。当然这里使用访问器属性一样能达到只读效果。
  3. 如果要求对用户的输入进行特殊处理,或者设置属性的依赖关系,就需要用到访问器属性了。

综上,访问器属性的功能最强大,但是在一般需求情况下,我们使用数据属性即可。

7. 能够操纵属性描述符的方法

7.1 为目标对象设置单个属性

设置单个属性可以使用 Object.defineProperty() 方法,要注意的是,对于同一个属性,不可以同时在描述符中指定属于数据描述符的 value,writable 和属于访问器描述符的 get,set,否则会报错。

7.2 为目标对象设置多个属性

设置多个属性可以使用 Object.defineProperties() 方法。

7.3 禁止目标对象扩展(不允许添加新属性)

禁止添加新属性可以使用 Object.preventExtensions() 方法,该方法接收一个目标对象传入,使用后该对象禁止添加新属性。使该对象禁止扩展。

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

 // 也不能使用Object.defineProperty方法进行扩展,会报错,报错如图7.3示
Object.defineProperty(obj, ‘c‘, {
    value: 3,
    writable: true,
    enumerable: true,
    configurable: true
});

7.4 密封目标对象(不允许扩展且不允许进行属性配置)

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

// demo7.4
var obj = {
    a:1
};
console.log(Object.getOwnPropertyDescriptor(obj, ‘a‘)); // {value: 1, writable: true, enumerable: true, configurable: true}
Object.seal(obj);
console.log(Object.getOwnPropertyDescriptor(obj, ‘a‘)); // {value: 1, writable: true, enumerable: true, configurable: false}
obj.a = 2;
console.log(obj.a); // 2

7.5 冻结目标对象(密封对象且不允许修改)

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

// demo7.5-1
var obj = {
    a:1
};
console.log(Object.getOwnPropertyDescriptor(obj, ‘a‘)); // {value: 1, writable: true, enumerable: true, configurable: true}
Object.freeze(obj);
console.log(Object.getOwnPropertyDescriptor(obj, ‘a‘)); // {value: 1, writable: false, enumerable: true, configurable: false}
obj.a = 2;
console.log(obj.a); // 1

有的人可能会想,那么此时我如果去修改访问器属性值呢?事实上,对访问器属性的修改实际是通过内部的数据属性为桥梁进行修改的,此时内部的数据属性已经无法修改了,那么对访问器的属性修改也是无效的了。

// demo7.5-2
// 对比demo 4.2.2-1
var obj = {
    _a: 1,
    _doubleA: 2
};
Object.defineProperty(obj, ‘a‘, {
    get: function() {
        return this._a;
    },
    // set方法能接收用户传入的值,并利用该值对对象的任一属性做操作
    set: function(val) {
        this._a = val;
        this._doubleA = 2 * this._a;
    }
});

console.log(Object.getOwnPropertyDescriptor(obj, ‘a‘));  // {get: ƒ, set: ƒ, enumerable: false, configurable: false}
console.log(Object.getOwnPropertyDescriptor(obj, ‘_a‘));  // {value: 1, writable: true, enumerable: true, configurable: true}
console.log(Object.getOwnPropertyDescriptor(obj, ‘_doubleA‘)); // {value: 2, writable: true, enumerable: true, configurable: true}
console.log(obj.a);  // 1
console.log(obj._a); // 1
console.log(obj._doubleA); // 2

// 冻结对象导致_a变成只读属性,从而依赖其返回的a和_doubleA也变成只读属性。此处将_a的writable和configurable属性设置为false,得出的结果会是一样的。
Object.freeze(obj);

obj.a = 2;
console.log(Object.getOwnPropertyDescriptor(obj, ‘_a‘));  // {value: 1, writable: false, enumerable: true, configurable: false}
console.log(Object.getOwnPropertyDescriptor(obj, ‘_doubleA‘)); // {value: 2, writable: false, enumerable: true, configurable: false}
console.log(obj.a);  // 1
console.log(obj._a); // 1

原文地址:https://www.cnblogs.com/aioverg/p/11400660.html

时间: 2024-10-02 11:30:39

属性特征的相关文章

OC中的属性特征

在刚开始学习oc的过程中,一直对声明完返回值后的属性特征不咋明白啥意思,今天特地找了一下资料,彻底的明白其中的意思. oc中的属性特征主要有assign,copy,retain这三个主要的,还有readonly,readwrite.   另外,atomic和nonatomic:以及strong,weak. assign主要是针对基础类型数据和c数据类型的简单赋值,而且它不调用索引计数器(retain count). retain主要是指调用oc中的对象,对oc中的对象进行赋值(主要针对NSObj

JavaScript之读取属性特征

使用Object.getOwnPropertyDescriptor方法读取属性特征 'use strict'; var person = { }; Object.defineProperties(person, { _age: { configurable: true, writable: true, enumerable: true, value: -1, }, age: { configurable: false, enumerable: false, get: function () {

SQL server中事务的四个属性特征(ACID)

事务的概念.类型和四个特征(ACID). 1.事务(Transaction)是并发控制的单位,是用户定义的一个操作序列.这些操作要么都做,要么都不做,是一个不可分割的工作单位. 通过事务,SQL Server能将逻辑相关的一组操作绑定在一起,以便服务器保持数据的完整性. 2.事务通常是以BEGIN TRANSACTION开始,以COMMIT或ROLLBACK结束. COMMIT表示提交,即提交事务的所有操作.具体地说就是将事务中所有对数据库的更新写回到磁盘上的物理数据库中去,事务正常结束. RO

js对象属性特征

enumerable和configurable (function(){ 'use strict'; var point={x:1,y:2,z:3}; Object.defineProperty(point,'x',{ enumerable:false,//对象属性是否可枚举 configurable:false //对象属性是否可配置,不能删除,注意值是可以修改的 }); delete point.x;//x属性不可配置,所以x属性没有被删除,在严格模式下会抛出错误,非严格模式忽略 conso

自组织特征映射神经网络(SOFM)

1981年芬兰 Helsink 大学的 T·Kohonen 教授提出一种自组织特征映射网 (Self-Organizing Feature Map , SOFM ), 又称 Kohonen 网 . Kohonen 认为 ,一个神经网络接受外界输入模式时, 将会分为不同的对应区域, 各区域对输入模式具有不同的响应特征,而且这个过程是自动完成的. 自组织特征映射正是根据这一看法提出来的 ,其特点与人脑的自组织特性相类似. 一.SOFM网生物学基础 生物学研究表明,在人脑感觉通道上,神经元的组织原理是

JavaOO的三大特征

在这周我学习了JavaOO的三大特征:继承.封装.多态,这三大特征让Java面向对象编程展现的玲离尽致. 首先是继承,继承则是一个类可以继承另一个类,那么另一个类则是这个类的父类,那么子类就拥有了父类的全部属性.继承的好处是大大减少了代码的重复性,增加了可维护性. 第二是封装,封装则是和访问修饰符密切相关的,在Java中有四个访问修饰符,分别是public protected deflaut private.对于以后类的属性基本上是由private(私有的)来修饰,好处是为了保护属性特征,然后用

访问器属性:setter()函数和getter()函数

1.干嘛用的? getter()函数:返回有效的值 setter()函数:调用它并传入数据,这个函数决定如何处理数据 2.具备哪些属性?如何定义? configurable(默认为true),enumerable(默认为true),get(默认为undefined),set(默认为undefined) 四个属性特征 3.具体应用? var book={_year:2017,edition:1}; Object.defineProperty(book,"year",{ get:funct

JavaScript笔记--数据属性和访问器属性

在JavaScript中最基本的创建一个对象的方法是new一个Object()的实例,然后再为其添加属性与方法,下例创建一个包含属性name的person对象,name属性的特征值为"xiaochang": var person = new Object(); person.name = "xiaochang"; person.say = function(){ console.log("Hi, my name is " + this.name)

面向对象的三大特征:继承 封装 多态

面向对象: 面向对象专注于由谁来解决这个过程,而调用者无需关注对象实现的细节 编程特点: 出现了一个个的类,从类中拿到对象,通过对象直接解决问题 类:具有一系列相同属性(特征)和方法(行为)的个体的集合 称为类 类是一个抽象的概念,只能说类具有哪些属性而不能直接对类进行赋值 例如 人类有身高这个属性,但是不能说人类的身高是180 对象:从类中拿出具有具体属性值的个体,称为对象 对象是从类中拿出的一个具体的个体,需要对属性进行具体的赋值 例如 人类有身高这个属性,张三是人类的一个个体,就可以说张三