# 对象属性

# 二、属性类型

# 1. 数据属性

数据属性包含一个数据值的位置。四个特性

  1. [[Configurable]] 可配置,定义能否 删除属性,修改属性特性,或修改未访问器属性,默认值 true
  2. [[Enumerable]] 可否通过 for-in 循环返回属性,默认值 true
  3. [[Writable]] 能否修改属性的值,默认值 true
  4. [[Value]] 包含这个属性的数据值,默认值 undefined
// 修改属性默认的特性,必须使用 Object.defineProperty(所在对象, 属性名, 描述符对象)
var person = {}

Object.defineProperty(person, 'name', {
  writable: false,
  value: 'myName'
})

// Configurable 决定了,能否 delete 属性
Object.defineProperty(person, 'name', {
  Configurable: false,
  value: 'myName2'
})

通过定义 writable 为 false,如果企图再次通过 Object.defineProperty 来定义 value值会报错:

Cannot redefine property: name

# 2. 访问器属性

包含一对儿 getter setter 函数,四个特性

  1. [[Configurable]]: 配置,可否修改属性的特性。默认 true
  2. [[Enumerable]]: 可否通过 for-in 遍历
  3. [[Get]]: 读取属性时调用的函数,默认 undefined
  4. [[Set]]: 写入属性时调用的函数,默认 undefined
var book = {
  _year: 2004, //表示此属性,仅被对象的方法修改,不要通过 book._year = xxx 的方式从外部赋值
  edition: 1
}

Object.defineProperty(book, "abc", {
  get: function() {
    return this._year
  },
  set: function(newValue) {
    if(newValue > 2004) {
      this._year = newValue
      this.edition += this._year - 2004
    }
  }
})

book.abc = 2005 // 某一个属性变化,导致其他属性变化
console.log(book.edition)

# 三、属性特性的定义与获取

# 3. 一次定义多个属性

Object.defineProperties(对象, 修改属性的对象)

var book = {}

Object.defineProperties(book, {
  _year: {
    value: 2004
  },

  edition: {
    value: 1
  },

  year: {
    get: function() {
      return this._year
    },

    set: function(newValue) {
      if(newValue > 2004) {
        this._year = newValue
        this.edition += newValue - 2004
      }
    }
  },

  })

# 4. 需要注意对象的创建方式不同,默认属性的差异

  • 字面量形式

    var book = {
      _year: 1212
    }
    console.log(Object.getOwnPropertyDescriptor(book, "_year"))
    /*
    { value: 1212,
      writable: true,
      enumerable: true,
      configurable: true }
    */
    
  • Object.defineProperty 创建

    var book = {}
    
    Object.defineProperty(book, _year, {
      value: 1212
    })
    
    /*
    { value: 1212,
      writable: false,
      enumerable: false,
      configurable: false }
    */
    

# 5. 一个属性,要么是 数据属性,要么是 访问器属性,二者不可兼得

let book = {}

Object.defineProperty(book, 'year', {
  get: function() {
    return this._year
  },

  set: function(newValue) {
    this._year = newValue
  },

  value: 2222
})

console.log(Object.getOwnPropertyDescriptor(book, 'year'))
// 报错 Invalid property descriptor.
// Cannot both specify accessors and a value or writable attribute.
  1. 在 es6 中块级作用域,里 有 var 变量,依然外部可以读取,let 变量 不可以
  2. Object.getOwnPropertyDescriptor(obj, props) 可针对所有对象使用,获取属性特性

# 疑问

String.prototype.lengthByte 拓展了 String 对象的方法,但为何必须调用时执行,而直接加在方法后执行就是0

str.lengthByte()  //可行

String.prototype.lengthByte = function() {

}() //不可行

# 其他知识

javascript 的每个对象都有 __proto__ 属性,但是只有函数对象有 prototype 属性。

  1. __proto__ 表示该函数对象的原型
  2. prototype表示使用new来执行该函数时(这种函数一般成为构造函数,后面会讲解),新创建的对象的原型。例如:
var d = new Date();
d.__proto__ === Date.prototype; //这里为true
Date.__proto__ === Object.__proto__  //这里为true

需要注意的是,这里的arguments不是一个数组,它只是一个有length属性的类数组对象(Array-like),它并不拥有数组的其他方法。

字面量(Array Literal) 的含义?

Last Updated: 5/14/2022, 11:38:45 AM