JavaScript高级程序设计(第4版)读书分享笔记记录
适用于刚入门前端的同志
- 创建自定义对象的通常方式是创建 Object 的一个新实例,然后再给它添加属性和方法。
let person = new Object()
person.name = 'Tom'
person.age = 18
person.sayName = function(){
//示 this.name 的值,这个属性会解析为 person.name。
console.log(this.name) // Tom
}
以上代码就创建了一个名为person的对象,有两个属性(name,age)和一个方法(sayName)。
- 使用对象字面量创建对象
let person = {
name:'Tom',
age:18,
sayName(){
console.log(this.name) //Tom
}
}
属性的类型
数据属性
- [[Configurable]]:表示属性是否可以通过 delete 删除并重新定义,是否可以修改它的特性,以及是否可以把它改为访问器属性。默认情况下,这个特性都是 true
- [[Enumerable]]:表示属性是否可以通过 for-in 循环返回。默认情况下,这个特性都是 true。
- [[Writable]]:表示属性的值是否可以被修改。默认情况下,这个特性都是 true。
- [[Value]]:包含属性实际的值。这就是前面提到的那个读取和写入属性值的位置。这个特性的默认值为 undefined。
let person = {}
Object.defineProperty(person,'name',{
writable:false,
configurable:false,
value:'Tom'
})
console.log(person.name) // Tom
//这里修改person对象的name值,是无效的,因为上面writable:false,就说明属性的值不可被修改
person.name = 'Jerry'
console.log(person.name) // Tom
//这里删除person对象的name属性,是删除不了的因为上面configurable:false,就说明该属性不能被delete
delete person.name
console.log(person.name) // Tom
注意:
- 在调用 Object.defineProperty()时,configurable、enumerable 和 writable 的值如果不指定,则都默认为 false。
- 此外,一个属性被定义为不可配置之后(false),就不能再变回可配置的了再次调用 Object.defineProperty()并修改任何非 writable 属性会导致错误
-
在不支持 Object.defineProperty()的浏览器中没有办法修改[[Configurable]]或[[Enumerable]]
例子:
const person = {name:"yd"}
Object.defineProperty(person,"age",{value:21})
person.age = 18
console.log(person) //{name: "jd",age:21}
console.log(Object.keys(person)) // ["name"]
解析:
在调用 Object.defineProperty()时,configurable、enumerable 和 writable 的值如果不指定,则都默认为 false。
使用 Object.defineProperty 方法添加的属性默认是不可枚举的,所以Object.keys(person)打印的日志只有["name"]一个属性
访问器属性
- [[Configurable]]:表示属性是否可以通过 delete 删除并重新定义,是否可以修改它的特性,以及是否可以把它改为数据属性。默认情况下,所有直接定义在对象上的属性的这个特性都是 true。
- [[Enumerable]]:表示属性是否可以通过 for-in 循环返回。默认情况下,所有直接定义在对象上的属性的这个特性都是 true。
- [[Get]]:获取函数,在读取属性时调用。默认值为 undefined。
- [[Set]]:设置函数,在写入属性时调用。默认值为 undefined。
访问器属性是不能直接定义的,必须使用 Object.defineProperty()。
例子:
// 定义一个对象,包含伪私有成员 year_和公共成员 edition
let book = {
year_: 2017,
edition: 1
}
Object.defineProperty(book ,"year",{
get(){
return this.year_
},
set(newVal){
if(newVal > 2017){
this.year_ = newVal
this.edition += newVal - 2017
}
}
})
console.log(book.year) // 2017
book.year = 2018
console.log(book.year) // 2018
console.log(book.edition) // 2
定义多个属性
let book = {};
Object.defineProperties(book, {
year_: {
value: 2017 ,
// writable:true
},
edition: {
value: 1 ,
// writable:true
},
year: {
get(){
return this.year_;
},
set(newValue){
console.log("1112222222222",newValue)
if (newValue > 2017) {
this.year_ = newValue;
console.log("1112222222222" ,this.year_)
this.edition += newValue - 2017;
}
}
}
})
console.log(book.year_) // 2017
console.log(book.year) // 2017
console.log(book.edition) // 1
//此时这里修改了year 的值 但是打印没变
book.year = 2018
console.log(book.year_) // 2017
console.log(book.year) // 2017
console.log(book.edition) // 1
注意:
let book = {};
Object.defineProperties(book, {
year_: {
value: 2017 ,
writable:true
},
edition: {
value: 1 ,
writable:true
},
year: {
get(){
return this.year_;
},
set(newValue){
console.log("1112222222222",newValue)
if (newValue > 2017) {
this.year_ = newValue;
console.log("1112222222222" ,this.year_)
this.edition += newValue - 2017;
}
}
}
})
console.log(book.year_) // 2017
console.log(book.year) // 2017
console.log(book.edition) // 1
book.year = 2018
console.log(book.year_) // 2018
console.log(book.year) // 2018
console.log(book.edition) // 1
读取属性的特性
使用 Object.getOwnPropertyDescriptor()方法可以取得指定属性的属性描述符。这个方法接收两个参数:属性所在的对象和要取得其描述符的属性名。返回值是一个对象
接上面的book例子:
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"
ECMAScript 2017 新增了 Object.getOwnPropertyDescriptors()静态方法,返回值是一个对象
接上面的book例子:
let descript = Object.getOwnPropertyDescriptors(book)
console.log(descript )
打印值:
合并对象
- 这个方法接收一个目标对象和一个或多个源对象作为参数。
- 注意:Object.assign()的属性拷贝是浅拷贝
- 同名属性替换,如果多个源对象都有相同的属性,则使用最后一个复制的值。
let dest ,src, result;
//一个源对象
dest = {}
src = {id:'src'}
result = Object.assign(dest,src)
console.log(result ) // {id:'src'}
//多个源对象
dest = {}
result = Object.assign(dest, { a: 'foo' }, { b: 'bar' });
console.log(result); // { a: foo, b: bar }
// 浅复制体现
dest = {}
src = { a:{b:1}}
result = Object.assign(dest ,src)
console.log(result) // { a:{b:2}} 因为是浅复制,值指向同一位置
console.log(result.a.b) // 1
src.a.b = 2
console.log(result.a.b) // 2
//覆盖属性
dest = {id:'dest'}
result = Object.assign(dest ,{id:'src',a:1},{id:'test',b:2})
console.log(result ) // {id:'test',a:1,b:2}
对象标识及相等判定
- 这个方法与===很像,用来比较两个值是否严格相等。
- 这个方法必须接收两个参数
Object.is("q","q"); // true
Object.is(1,1); // true
Object.is([1],[1]); // false
Object.is({q:1},{q:1}); // false
与 === 的区别
//一是+0不等于-0
console.log( Object.is(+0,-0) ); //false
console.log( +0 === -0 ) //true
//二是NaN等于本身
console.log ( Object.is(NaN,NaN) ); //true
console.log (NaN === NaN) //false
增强的对象语法
属性简写
ES6允许对象的属性直接写变量,这时候属性名是变量名,属性值是变量值。
const age = 12;
const name = "Amy";
const person = {age, name};
console.log(person) //{age: 12, name: "Amy"}
//等同于
const person = {age: age, name: name}
可计算属性
const nameKey = 'name';
const ageKey = 'age';
const jobKey = 'job';
let person = {
[nameKey]: 'Matt',
[ageKey]: 27,
[jobKey]: 'Software engineer'
};
console.log(person); // { name: 'Matt', age: 27, job: 'Software engineer' }
简写方法名
const person = {
sayHi(){
console.log("Hi");
}
}
person.sayHi(); //"Hi"
//等同于
const person = {
sayHi:function(){
console.log("Hi");
}
}
person.sayHi();//"Hi"
对象解构
// 使用对象解构
let person = {
name: 'Matt',
age: 27
};
let { name: personName, age: personAge } = person;
console.log(personName); // Matt
console.log(personAge); // 27
let person = {
name: 'Matt',
age: 27
};
let { name, age } = person;
console.log(name); // Matt
console.log(age); // 27
let personName, personAge;
let person = {
name: 'Matt',
age: 27
};
({name: personName, age: personAge} = person);
console.log(personName, personAge); // Matt, 27
Object的常用方法
Object.keys
语法:
Object.keys(obj)
参数:要返回其枚举自身属性的对象
返回值:一个表示给定对象的所有可枚举属性的字符串数组
实际用法:
- 处理对象,返回可枚举的属性数组
let person = {name:"小美",age:25,address:"都",getName:function(){}}
Object.keys(person) // ["name", "age", "address","getName"]
注意:使用 Object.defineProperty 方法添加的属性默认是不可枚举的,具体见上面例子
- 处理字符串,返回索引值数组
let str = "12345字符串"
Object.keys(str) // ["0", "1", "2", "3", "4", "5", "6", "7"]
- 处理数组,返回索引值数组
let arr = [1,2,3,4,5,6]
Object.keys(arr) // ["0", "1", "2", "3", "4", "5"]
Object.values
语法:
Object.values(obj)
参数:被返回可枚举属性值的对象 返回值:一个包含对象自身的所有可枚举属性值的数组。
实际用法:
- 处理对象,返回可枚举属性值数组
let person = {name:"小美",age:25,address:"成都",getName:function(){}}
Object.keys(person) // ["小美", 25, "成都",function]
- 处理字符串,返回字符串数组
let arr = Object.values('test')
console.log(arr) //['t', 'e', 's', 't']
Object.entries
语法:
Object.entries(obj)
参数:可以返回其可枚举属性的键值对的对象。 返回值:给定对象自身可枚举属性的键值对数组。
实际用法:
- 处理对象
const obj = { name: '小美', age: 25, address: '成都' };
const res = Object.entries(obj)
console.log(res);
- 处理数组
const obj = [1,2,3,4,5,6]
const res = Object.entries(obj)
console.log(res);