一、创建对象的方式
-
字面量
let a = {}
-
new关键字
let b = new Object()
-
Object.create()方法
let c = Object.create(Object.prototype)
二、原型链
-
代码理解
// 1、原型 => 类 或 函数 // 2、原型对象 => 对象 // 3、实例对象 => 创建的实例 // 4、相互转化 // 原型 class Person { } console.log('原型:', Person) // 原型: [class Person] // 原型对象添加属性、方法 Person.prototype.username = '默认用户' Person.prototype.password = '默认密码' Person.prototype.login = function login(username, password) { console.log(`${username}登录成功!`) } console.log('原型对象:', Person.prototype) // 原型对象: { username: '默认用户', password: '默认密码', login: [Function: login] } // 原型对象 转 原型 console.log(Person.prototype.constructor === Person) // true // 创建实例对象 const person = new Person(); person.login('小李', '123456') // 小李登录成功! const person2 = new Person.prototype.constructor() console.log(person2.username) // 默认用户 // 实例对象 转 原型对象 console.log(person.__proto__ === Person.prototype) // true console.log(Object.getPrototypeOf(person) === Person.prototype) // true // 实例对象到原型 console.log(person.__proto__.constructor === Person) // true => 可以用来检验某对象是否是该类的实例对象
三、Object对象
-
常用方法
- Object.create():创建对象
- Object.is():判断两个对象是否是同一个对象
- Object.hasOwn():判断某个对象自身是否包含某个属性
- Object.getOwnPropertyDescriptor():获取指定对象某个自有属性描述符
- Object.getOwnPropertyDescriptors():获取指定对象所有自有属性描述符
- Object.getPrototypeOf():获取实例对象的原型对象
- Object.setPrototypeOf():设置某个实例对象的原型对象
- Object.getOwnPropertyNames():获取某个对象所有自身属性
- Object.getOwnPropertySymbols():获取某个对象所有自身符号属性
- Object.defineProperty():给对象定义或修改属性(存在局限性)
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>测试</title> <script> // 1、创建对象 let a = Object.create(Document.prototype) console.log(a.__proto__.constructor === Document) // true // 2、判断两个对象是否是同一个对象 // window、self、top、parent也是一个补环境检测点 console.log(Object.is(window, self)) // true console.log(Object.is(window, top)) // true console.log(Object.is(window, parent)) // true console.log(Object.is(window, self.top.parent)) // true // 3、判断对象自身是否含有某个属性 console.log(Object.hasOwn(document, 'location')) // true console.log(Object.hasOwn(document, 'cookie')) // false // 4、获取原型对象 console.log(Object.getPrototypeOf(document)) // HTMLDocument {Symbol(Symbol.toStringTag): 'HTMLDocument', onreadystatechange: undefined, onm ouseenter: undefined, onm ouseleave: undefined, constructor: ƒ} // 5、获取指定对象的指定属性描述符 console.log(Object.getOwnPropertyDescriptor(document, 'location')) // {enumerable: true, configurable: false, get: ƒ, set: ƒ} // 6、获取指定对象所有自有属性描述符 console.log(Object.getOwnPropertyDescriptors(document)) // {location: {…}} // 7、设置原型对象 let obj = {} Object.setPrototypeOf(obj, Document.prototype) console.log(obj.__proto__) // Document {…} // 8、获取自身所有属性 console.log(Object.getOwnPropertyNames(document)) // ['location'] // 9、获取自身所有符号属性 console.log(Object.getOwnPropertySymbols(Document.prototype)) // [Symbol(Symbol.toStringTag), Symbol(Symbol.unscopables)] </script> </head> <body> </body> </html>
-
Object.defineProperty()方法及属性描述符
// 1、初始化对象时定义属性 let user = { name: '小李' } // 2、添加属性 user.age = 28 // 3、Object.defineProperty() // 第一个参数是对象,第二个参数是属性,第三个参数是一个属性描述符(对象) Object.defineProperty(user, 'height', { enumerable: true, // 是否可遍历,设为false,则遍历时不会显示该属性 configurable: true, // 是否可配置,设为false,则后续继续调用Object.defineProperty定义该属性时会报错 writable: true, // 是否可写,设为false,后续修改该属性不会生效 value: 175 // 设置属性具体值 }) // 4、属性描述符中,(writable、value)和(get、set)不能同时使用 // 属性描述符第二种写法(推荐) let tmpWeight = 120 Object.defineProperty(user, 'weight', { enumerable: true, configurable: true, get: function (){ console.log('正在获取属性') return tmpWeight }, set: function (value){ console.log('正在设置属性') tmpWeight = value } }) user.weight = 130 // 设置属性 console.log(user.weight) // 获取属性
-
判断对象类型
- typeof
- Object.prototype.toString.call() -- 推荐
// 1、typeof console.log(typeof '1') // string console.log(typeof 1) // number console.log(typeof true) // boolean console.log(typeof {}) // object console.log(typeof []) // object 不容易区分 console.log(typeof null) // object 不容易区分 console.log(typeof undefined) // undefined console.log(typeof Symbol()) // symbol // 2、Object.prototype.toString.call console.log(Object.prototype.toString.call('1')) // [object String] console.log(Object.prototype.toString.call(1)) // [object Number] console.log(Object.prototype.toString.call(true)) // [object Boolean] console.log(Object.prototype.toString.call({})) // [object Object] console.log(Object.prototype.toString.call([])) // [object Array] console.log(Object.prototype.toString.call(null)) // [object Null] console.log(Object.prototype.toString.call(undefined)) // [object Undefined] console.log(Object.prototype.toString.call(Symbol())) // [object Symbol]
四、Reflect对象
-
简介
- Reflect对象时ES6为了操作对象,而提供的新API
- 把Object对象的一些方法放到Reflect对象上
- 修改某些Object对象的返回值,让其变得合理,比如defineProperty方法在无法定义属性时不会报错,而是返回false
- 让Object操作都变成函数行为,比如in和delete操作,变成了 Reflect.has(obj, name) 和 Reflect.delete(obj, name)
-
apply()
- Function.prototype.apply(thisArg, args)
// Reflect.apply(target, thisArg, args) const obj = { age: 28 } function fn(a, b, c){ return this.age + a + b + c } // 旧写法 console.log(fn.apply(obj, [1, 2, 3])) // 34 // 新写法 console.log(Reflect.apply(fn, obj, [1, 2, 3])) // 34
- Function.prototype.apply(thisArg, args)
-
construct()
- new 构造函数()
// Reflect.construct(target, args) class Person{ constructor(name, age) { this.name = name this.age = age } } // 旧写法 const p1 = new Person('小李', 28) console.log(p1) // Person { name: '小李', age: 28 } // 新写法 const p2 = Reflect.construct(Person, ['小王', 30]) console.log(p2) // Person { name: '小王', age: 30 }
- new 构造函数()
-
get()
- obj.prop
// Reflect.get(target, prop, receiver) const obj = { name: '刘德华', age: 40, get info(){ return `${this.name}:${this.age}岁` } } console.log(Reflect.get(obj, 'name')) // 刘德华 console.log(Reflect.get(obj, 'age')) // 40 console.log(Reflect.get(obj, 'info')) // 刘德华:40岁 // 访问对象中没有的属性,返回undefined console.log(Reflect.get(obj, 'height')) // undefined // receiver参数能够改变get属性访问器中的this指向 const objNew = { name: '张学友', age: 38 } console.log(Reflect.get(obj, 'info', objNew)) // 张学友:38岁
- obj.prop
-
set()
- obj.prop = value
// Reflect.set(target, prop, value, receiver) const obj = { name: '刘德华', set info(value){ this.name = value } } console.log(Reflect.set(obj, 'info', '周润发')) // true console.log(obj.name) // 周润发 const objNew = { name: '张学友' } // receiver参数能改变set属性访问器中的this指向 if(Reflect.set(obj, 'info', '吴彦祖', objNew)){ console.log(obj.name) // 周润发 console.log(objNew.name) // 吴彦祖 }
- obj.prop = value
-
has()
- prop in obj
// Reflect.has(target, prop) const obj = { name: '刘德华', age: 40 } // 旧写法 console.log('name' in obj) // true console.log('gender' in obj) // false // 新写法 console.log(Reflect.has(obj, 'name')) // true console.log(Reflect.has(obj, 'gender')) // false
- prop in obj
-
deleteProperty()
- delete obj.prop
// Reflect.deleteProperty(target, prop) const obj = { name: '刘德华', age: 40 } // 旧写法 // delete obj.age // 新写法 // 属性能删除则返回true,不能删除则返回false,被删除的属性依然存在 console.log(Reflect.deleteProperty(obj, 'age')) // true console.log(obj) // { name: '刘德华' } Reflect.defineProperty(obj, 'gender', { value: '男', configurable: false, // 不可配置,所以该属性无法被删除 enumerable: true, writable: true }) console.log(obj) // { name: '刘德华', gender: '男' } console.log(Reflect.deleteProperty(obj, 'gender')) // false console.log(obj) // { name: '刘德华', gender: '男' }
- delete obj.prop
-
其它方法对照
// 新写法 // Reflect.defineProperty(target, prop, descriptor) // Reflect.getPrototypeOf(target) // Reflect.setPrototypeOf(target, prototype) // Reflect.isExtensible(target) // Reflect.preventExtensions(target) // Reflect.ownKeys(target) // 旧写法 // Object.defineProperty(target, prop, descriptor) // Object.getPrototypeOf(target) // Object.setPrototypeOf(target, prototype) // Object.isExtensible(target) // Object.preventExtensions(target) // Object.getOwnPropertyNames(target) + Object.getOwnPropertySymbols(target)
五、Proxy对象
-
简介
- 可以理解为拦截器,拦截对象的属性读取和设置操作
const person = { name: '周杰伦', phone: '18888888888' } let personHandler = { // 拦截属性的获取 get: function (target, prop, receiver){ // console.log(receiver) // console.log(`正在获取属性:${prop}`) if(prop === 'phone'){ return '经纪人电话: 13066666666' } return Reflect.get(target, prop, receiver) }, // 拦截属性的设置 set: function (target, prop, value, receiver){ // console.log(`正在设置属性:${prop}`) if(prop === 'gender'){ console.log('无法设置gender属性') }else{ return Reflect.set(target, prop, value, receiver) } } } // 创建代理对象,第一个参数是被代理的对象,第二个参数是处理对象 const proxy = new Proxy(person, personHandler) // 通过代理获取对象的属性 console.log(proxy.name) // 周杰伦 console.log(proxy.phone) // 经纪人电话: 13066666666 // 通过代理设置对象的属性 proxy.gender = '男' proxy.age = 30 // gender属性无法设置 console.log(person.gender) // undefined console.log(person.age) // 30
- 可以理解为拦截器,拦截对象的属性读取和设置操作
六、Promise对象
-
简介
- Promise就是JS中专门用来存储异步代码的对象,可以确保异步代码的执行和返回结果
-
创建
- 创建Promise对象,需要指定一个回调函数作为参数,然后将需要执行的代码编写到该回调函数中
- 回调函数参数
- resolve:在代码正常执行时,来设置返回值
- reject(可选):在代码执行出错时,来设置错误信息
- 回调函数参数
- 创建Promise对象,需要指定一个回调函数作为参数,然后将需要执行的代码编写到该回调函数中
-
执行
- 顺利执行时,会执行then()方法,并将resolve返回的结果作为参数,传递给then()方法内的回调函数
- 执行异常时,会执行catch()方法,并将错误信息传递给内部的回调函数
// 创建Promise对象,正常执行,返回'顺利执行' const promise1 = new Promise((resolve, reject) => { setTimeout(() =>{ resolve('顺利执行') console.log('异步代码') // 会先执行该句代码,再返回执行结果'顺利执行' }, 2000) }) // 创建Promise对象,返回报错信息'执行异常' const promise2 = new Promise((resolve, reject) => { setTimeout(() =>{ reject('执行异常') console.log('异步代码') }, 2000) }) // 当Promise对象中的代码顺利执行时,会执行then()方法,并将resolve返回的结果作为参数,传递给then()方法内的回调函数 promise1 .then(result => console.log(result)) .catch(e => console.log(e)) // 当Promise对象中的代码返回错误信息时,会调用catch()方法,并将错误信息作为参数,传递给catch()方法内的回调函数 promise2 .then(result => console.log(result)) .catch(e => console.log(e))
-
then的链式调用
- 如果上一个then()中的返回值不是Promise对象,则将该返回值直接传递给下一个then()
- 如果上一个then()中的返回值是Promise对象,则将Promise对象中resolve返回值传给下一个then()
// 定义3个函数,分别返回promise对象 function fn1(n){ return new Promise(resolve => { setTimeout( () => resolve(n + 1), 1000 ) }) } function fn2(n){ return new Promise(resolve => { setTimeout( () => resolve(n + 2), 1000 ) }) } function fn3(n){ return new Promise(resolve => { setTimeout( () => resolve(n + 3), 1000 ) }) } // 如果上一个then()的返回值不是Promise对象,则将该返回值传给下一个then // 因此下面执行结果是:30 fn1(10) .then(n => 20) .then(n => 30) .then(n => console.log(n)) .catch(e => console.log(e)) // 如果上一个then()的返回值是Promise对象,则将上一个Promise对象中resolve返回值传给下一个then // 因此下面执行结果是:10+1+2+3 = 16 fn1(10) .then(n => fn2(n)) .then(n => fn3(n)) .then(n => console.log(n)) .catch(e => console.log(e))