面对对象编程听起来很Java,Java老程序可能对于它的理解很深,那js中的对象又是如何实现,有什么作用么?随着我的笔记一起来了解吧。
对象是啥
在某一种意义上对象就是一组没有任何规的值。它的每个属性和方法都有一个名称来标识。
创建自定义对象就是创建一个Object实例
let person = new Object();
person.name = "Nicholas";
person.age = 29;
person.job = "Software Engineer";
person.sayName = function() {
console.log(this.name);
};
// 都是相等的
let person = {
name: "Nicholas",
age: 29,
job: "Software Engineer",
sayName() {
console.log(this.name);
}
};
属性类型
开发者不能在 JavaScript 中直接访问这些特性。为了将某个特性标识为内部特性,规范会用两个中括号把特性的名称括起来。属性:数据属性和访问器属性。
- 数据属性
Configurable:属性是否可以通过 delete 删除并重新定义,是否可以修改它的特性,以及是否可以把它改为访问器属性。
Enumerable:表示属性是否可以通过 for-in 循环返回。
Writable:表示属性的值是否可以被修改
Value:包含属性实际的值。默认值是undefined - 访问器属性
Configurable:表示属性是否可以通过 delete 删除并重新定义,是否可以修改它的特性,以及是否可以把它改为数据属性。
Enumerable: 表示属性是否可以通过 for-in 循环返回。
Get:获取函数,在读取属性时调用,默认值为 undefined
Set:设置函数,在写入属性时调用,默认值为 undefined - 定义多个属性
在一个对象上同时定义上多个属性的可能性是非常大的。Object.defineProperties():通过多个描述符一次性定义多个属性。接收两个参数 一个属性的对象名和对象
let book = {};
Object.defineProperties(book, {
year_: {
value: 2017
},
edition: {
value: 1
},
year: {
get() {
return this.year_;
},
set(newValue) {
if (newValue > 2017) {
this.year_ = newValue;
this.edition += newValue - 2017;
}
}
}
});
读取属性的特性
Object.getOwnPropertyDescriptor()取得指定属性的属性描述符,接收两个参数对象和取得其描述符的属性名。
let book = {};
Object.defineProperties(book, {
year_: {
value: 2017
},
edition: {
value: 1
},
year: {
get: function() {
return this.year_;
},
set: function(newValue){
if (newValue > 2017) {
this.year_ = newValue;
this.edition += newValue - 2017;
}
}
}
});
let descriptor = Object.getOwnPropertyDescriptor(book, "year_");
console.log(descriptor.value); // 2017
console.log(descriptor.configurable); // false
console.log(typeof descriptor.get); // "undefined"
let descriptor = Object.getOwnPropertyDescriptor(book, "year");
console.log(descriptor.value); // undefined
console.log(descriptor.enumerable); // false
console.log(typeof descriptor.get); // "function"
合并对象
把源对象所有的本地属性一起复制到目标对象上。有时候会叫做混入mixin。
Object.assign():接收一个目标对象和一个或多个源对象作为参数,将每个源对象中可枚举(Object.propertyIsEnumerable()返回 true)和自有(Object.hasOwnProperty()返回 true)属性复制到目标对象。以字符串和符号为键的属性会被复制。使用源对象上的 get取得属性的值,使用目标对象上的set设置属性的值。
dest = {};
result = Object.assign(dest, { a: 'foo' }, { b: 'bar' });
console.log(result); // { a: foo, b: bar }
对象标识及相等判定
// 这些都不能判断
// 这些是===符合预期的情况
console.log(true === 1); // false
console.log({} === {}); // false
console.log("2" === 2); // false
// 这些情况在不同 JavaScript 引擎中表现不同,但仍被认为相等
console.log(+0 === -0); // true
console.log(+0 === 0); // true
console.log(-0 === 0); // true
// 要确定 NaN 的相等性,必须使用极为讨厌的 isNaN()
console.log(NaN === NaN); // false
console.log(isNaN(NaN)); // true
Object.is(),这个方法与===很像,但同时也考虑到了上述边界情形。
console.log(Object.is(true, 1)); // false
console.log(Object.is({}, {})); // false
console.log(Object.is("2", 2)); // false
// 正确的 0、-0、+0 相等/不等判定
console.log(Object.is(+0, -0)); // false
console.log(Object.is(+0, 0)); // true
console.log(Object.is(-0, 0)); // false
// 正确的 NaN 相等判定
console.log(Object.is(NaN, NaN)); // true
增强的对象语法
- 属性名简写
function makePerson(name) {
return {
name
};
}
let person = makePerson('Matt');
console.log(person.name); // Matt
- 可计算属性
const nameKey = 'name';
const ageKey = 'age';
const jobKey = 'job';
let uniqueToken = 0;
function getUniqueKey(key) {
return `${key}_${uniqueToken++}`;
}
let person = {
[getUniqueKey(nameKey)]: 'Matt',
[getUniqueKey(ageKey)]: 27,
[getUniqueKey(jobKey)]: 'Software engineer'
};
console.log(person); // { name_0: 'Matt', age_1: 27, job_2: 'Software engineer' }
- 简写方法名
const methodKey = 'sayName';
let person = {
[methodKey](name) {
console.log(`My name is ${name}`);
}
}
person.sayName('Matt'); // My name is Matt
对象解构
使用一条语句使用嵌套数据或者实现多个赋值操作
let person = {
name: 'Matt',
age: 27
};
function printPerson(foo, {name, age}, bar) {
console.log(arguments);
console.log(name, age);
}
function printPerson2(foo, {name: personName, age: personAge}, bar) {
console.log(arguments);
console.log(personName, personAge);
}
printPerson('1st', person, '2nd');
// ['1st', { name: 'Matt', age: 27 }, '2nd']
// 'Matt', 27
printPerson2('1st', person, '2nd');
// ['1st', { name: 'Matt', age: 27 }, '2nd']
// 'Matt', 27