JS面向对象设计-理解对象

不同于其他面向对象语言(OO,Object-Oriented),JS的ECMAScript没有类的概念,
它把对象定义为"无序属性(基本值、对象、函数)的集合",类似于散列表.
每个对象都是基于一个引用类型(原生类型、自定义类型)创建的.

1. 理解对象

创建自定义对象(Object构造函数、对象字面量).

// Object构造函数:创建一个Object实例,再为实例添加属性和方法.
var person = new Object();
person.name = "xiao";
person.getName = function() {
    console.log(this.name)      // 被解析为person.name
}

// 对象字面量: 属性在创建时带有一些特征值,JS通过特征值来定义它们的行为.
var person = {
    name: "xiao";
    getName: function() {
        console.log(this.name)
    }
}

1.1 属性类型(数据属性、访问器属性)

[[ ]]: 内部值(内部才用的特性)实现JS引擎,描述属性各种特征,JS不能直接访问.

1.1.1 数据属性

  • [[Configurable]]可用delete删除属性从而重新定义属性,修改属性特性、改为访问器属性.
  • [[Enumberable]]可用for-in循环返回属性.
  • [[Writable]]可修改属性值.
  • [[Value]]属性的数据值,默认为undefined.

ps. 直接在对象上定义的属性,他们的Configurable,Enumberable,Writable特性都为true.

修改属性默认的特性:Object.defineProperty()

/*
* 参数
* 1.属性所在对象
* 2.属性名字
* 3.一个描述符对象,描述符对象的属性必须是(configurable、enumerable、writable、value)
*/
var person = {};
Object.defineProperty(person, "name", {
    writable: false,        // 属性只读
    value: "xiao"
})
console.log(person.name);   // "xiao"
person.name = "da";         // 非严格模式下被忽视,严格模式下报错
console.log(person.name);   // "xiao"
// 一旦属性定义为不可配置,将不能再把它变回可配置.
Object.defineProperty(person, "name", {
    configurable: false,    // 属性不可配置
    value: "xiao"
})

ps. 用Object.defineproperty()方法创建新属性,如果不指定,Configurable,Enumberable,Writable特性默认为false.

1.1.2 访问器属性

不包含数据值,包含一对getter、setter函数(都不是必需的)

  • [[Configurable]]可用delete删除属性从而重新定义属性,修改属性特性、改为数据属性.
  • [[Enumberable]]可用for-in循环返回属性.
  • [[Get]]读取属性时调用的函数,默认为undefined.
  • [[Set]]写入属性时调用的函数,默认为undefined.

ps. 访问器属性不能直接定义,必须使用Object.defineProperty()

// 常见使用方式:设置一个属性的值会导致其他属性发生变化
var book = {
    _year: 2018,            // 只能通过对象方法访问的属性
    edition: 1
};

Object.defineProperty(book, "year", {
    get: function() {           // __definGetter__
        return this._year;
    },
    set: function(newValue) {   // __definSetter__
        if (newValue > 2018) {
            this._year = newValue;
            this.edition += newValue - 2018;
        }
    }
});

book.year = 2019;           // 修改year属性会导致_year变成2019
console.log(book.edition);  // edition变成2

在不支持Object.definProperty()方法的浏览器中不能修改[[Configurable]]和[[Enumberable]]

1.2 定义多个属性

Object.defineProperties()一次定义多个属性

/*
* 参数
* 1.要添加或修改其属性的对象
* 2.第二个对象的属性与第一个对象要添加或修改的属性一一对应
*/
var book = {};
Object.defineProperties(book, {
    _year: {
        writable: true,
        value: 2018
    },
    edition: {
        writable: true,
        value: 1
    },
    year: {
        get: function() {
            return this._year;
        },
        set: function(newValue) {
            if (newValue > 2018) {
                this._year = newValue;
                this.edition += newValue - 2018;
            }
        }
    }
})

1.3 读取属性特性

Object.getOwnPropertyDescriptor()取得给定属性的描述符,返回值是一个对象(属性特有的特性)。

/*
* 参数
* 1.属性所在对象
* 2.要读取其描述符的属性名称
*/
var descriptor = Object.getOwnPropertyDescriptor(book, "_year");
console.log(descriptor.value);             // 2018
console.log(descriptor.configurable);      // false
console.log(descriptor.get);               // "undefined",是数据属性,不是访问器属性

var descriptor = Object.getOwnPropertyDescriptor(book, "year");
console.log(descriptor.value);             // undefined,是访问器属性,不是数据属性
console.log(descriptor.configurable);      // false
console.log(descriptor.get);               // "function",是一个指向getter函数的指针

在JS中可以针对任何对象(包括DOM、BOM)使用Object.getOwnPropertyDescriptor()方法.

原文地址:https://www.cnblogs.com/LittlePANDA-ZSJ/p/10963990.html