概述:
Object 这个类是所有类的父类,也就是说它的方法和属性所有的对象都可以使用。Object的相关方法和属性是提供给其他的对象进行使用的。
属性
-
__proto__ :表示对象的原型指定当前构造函数的原型prototype
console.log({}.__proto__) //指向对应的Object的原型prototype
-
constructor :表示对象的构造函数
console.log({}.constructor) //指向Object构造函数
原型方法
- hasOwnProperty :判断本身是否具备这个属性 不包含原型上的
- isPrototypeof :判断当前对象是否存在原型链上
- propertyIsEnumerable :判断属性是否枚举
- toString :将对象转为字符串
- toLocalString :将对象转为本地格式字符串
- valueOf :得到本身的值
- 四个废弃的方法
-
hasOwnProperty (判断本身是否具备这个属性 不包含原型上的) *
//原型添加的属性
Object.prototype.age = 18
//本身的对象
let obj = {
name:'jack'
}
obj.sex = '男'
console.log(obj.age) //18 原型上的属性
console.log(obj.name) //本身的属性
//hasOwnProperty 判断对象本身是否具备属性 不包含原型上的属性的
//传入属性名
console.log(obj.hasOwnProperty('name'))//true
console.log(obj.hasOwnProperty('age')) //false
console.log(obj.hasOwnProperty('sex'))//true
-
isPrototypeof 判断当前对象是否存在原型链上 *
class Person{
constructor(){
this.name = 'tom'
}
}
class Child extends Person{
constructor(){
super()
this.age = 19
}
}
let child = new Child()
let person = new Person()
console.log(child.isPrototypeOf(person))//false child对象是否存在于person的原型链上
console.log(person.isPrototypeOf(child))//false person是否存在于child的原型链上
//判断是否存在原型链上 传入的是对应的对象
console.log(Person.prototype.isPrototypeOf(child)) //true 对应的Person的原型是否存在于child的原型链上
//将对应的child的原型进行赋值
child.__proto__ = person
//isPrototypeOf 传入的是对应查找原型链的对象
console.log(person.isPrototypeOf(child)) //true person对象是否存在于child的原型链上
-
propertyIsEnumerable 判断属性是否枚举(是否可以被for in遍历)*
//判断是否可以被for in遍历(是否枚举)propertyIsEnumerable
class Animal{
constructor(){
this.name = 'dog'
this.run = ()=>{}
}
//不能被枚举的
eat(){
}
}
let animal = new Animal()
animal.age = 18 //默认的赋值对应的属性可以被枚举
for(var key in animal){
console.log(key) //name run age
}
//检索是否可以枚举 (for in只能遍历可以枚举的属性)
console.log(animal.propertyIsEnumerable('run')) //true
console.log(animal.propertyIsEnumerable('name')) //true
console.log(animal.propertyIsEnumerable('age')) //true
console.log(animal.propertyIsEnumerable('eat')) //false
-
toString 将对象转为字符串、toLocalString 将对象转为本地格式字符串
-
valueOf 得到本身的值
class Animal {
constructor() {
//可枚举
this.color = 'pink'
}
// 不可枚举
Jump() {
console.log('跳得好高丫');
}
}
class Dog extends Animal {
constructor() {
super()
this.bark = function() {
console.log('汪汪');
}
}
}
let animal = new Animal()
let dog = new Dog()
//toString 转为字符串
console.log(Object.prototype.toString.call(new Animal())); //[object Object]
console.log(dog.valueOf());
结果:
-
废弃的四个方法
- __defineGetter__ :定义getter函数
- __defineSetter__ :定义setter函数
- __lookUpGetter__ :返回getter函数
- __lookUpSetter__ :返回setter函数
//废弃的四个方法
let obj1 = {
name: 'jack ',
age: 18
}
let _obj = {
name: 'jack ',
age: 18
}
//__defineGetter__ __defineSetter__ 定义getter和setter方法
//传递的属性名 和对应的处理函数
obj1.__defineGetter__('name', () => {
console.log('执行了')
return _obj.name //getter不允许调用自身
})
obj1.__defineSetter__('age', (value) => {
// obj1.age = value 报错 栈溢出
_obj.age = value
})
console.log(obj1.name) //访问getter 获取getter中的返回值
obj1.age = 30 //调用setter方法
//__lookupGetter__ __lookupSetter__ 返回对应的getter方法和setter方法
console.log(obj1.__lookupGetter__('name'))
console.log(obj1.__lookupSetter__('age'))
结果:
静态方法
- Object.assign :浅拷贝对象
- Object.create :创建一个对象
- Object.keys :返回对象所有的key组成的数组
- Object.values :返回对象所有的value组成的数组
- Object.entries :返回对象所有的键值对组成的数组
- Object.is :判断俩个对象是否一致
- Object.getPrototypeOf :获取原型
- Object.setPrototypeOf :设置原型
-
Object.assign 将传入的对象的内容填入第一个传入的对象内容内,返回的是第一个对象 *
//里面可以传入任意对象 将对应的后面的参数的内容填入到第一个对象中 返回第一个对象
let first = {
name: 'jack ',
likes: ['苹果']
}
let object = Object.assign(first, {
age: 18
}, {
sex: '男'
})
console.log(object) //{name:'jack',age:18,sex:'男'}
console.log(first == object) //true
console.log(first)
//object.assign 可以完成对象的浅拷贝(拷贝第一层值 深层拷贝地址 产生新的对象)
let copyObj = Object.assign({}, first)
console.log(copyObj == first) //false
//第二层拷贝地址 copyObj的likes对应的地址 和 first的likes的地址是一样的
console.log(copyObj.likes == first.likes) //true
-
Object.create 创建一个对象 *
//根据传入的内容来创建对应的内容
let first1 = {
name: 'jack '
}
//create它是将对应的传入的对象放入创建对象的原型上
let newObj = Object.create(first1) //根据传入的first来创建新的对象
console.log(newObj)
let obj = create(first1)
console.log(obj)
//简单实现一下Object的create方法
function create(obj) {
//创建一个新的对象
let newObj = {}
//将传入的对象放入新的对象的原型上
newObj.__proto__ = obj
//返回这个新的对象
return newObj
}
-
Object.keys 返回对象所有的key组成的数组
-
Object.values 返回对象所有的value组成的数组
-
Object.entries 返回对象所有的键值对组成的数组
let obj = {
name: ' hello ',
age: '17 '
}
class Person {
constructor() {}
//不可枚举的
eat() {}
}
//原型上的属性
Person.prototype.age = 18
//返回都是数组
console.log(Object.keys(obj)) //所有key的数组
console.log(Object.values(obj)) //value的数组
console.log(Object.entries(obj)) //所有的键值对 组成的二维数组
//Object.keys不包含不可枚举的属性 也不包含原型上的属性
let person = new Person()
console.log(Object.keys(person))
//for in不包含不可枚举的属性 包含原型上的属性
for (var key in person) {
console.log(key)
}
-
Object.is 判断俩个对象是否一致
//Object.is判断两个对象是否一致
let first = { }
let last = { }
console.log ( Object . is( first , last ) ); //false
-
Object.getPrototypeOf 获取原型
-
Object.setPrototypeOf 设置原型
function Person() {}
Person.prototype.age = 19
let person = new Person()
console.log(Object.getPrototypeOf(person)); //{age: 19, constructor: ƒ}
let obj = {
name: 'jack'
}
//将obj做为person的原理
Object.setPrototypeOf(person, obj)
console.log(obj.isPrototypeOf(person)); //true
console.log(person); //Person {}
对象相关操作限制的方法 *
- preventExtensions 不可扩展 :不能进行内容添加 (判断是否可扩展 isExtensible)
- seal 密封 :只能查询和修改,其他操作不允许(判断是否密封 isSealed )
- freeze 冻结 :只能查询(isFrozen 判断是否冻结)
//查询都能做的 不然的话对应的对象创建就没有意义
let obj = {
name: 'jack '
}
//不可扩展 返回当前的对象
Object.preventExtensions(obj)
//检测是否可以扩展
console.log(Object.isExtensible(obj)) //false
//添加新的属性
obj.age = 18 //无效
obj.name = 'tom' //改
console.log('name' in obj) //查询
delete obj.name //删除
console.log(obj)
//密封 修改和查询其他操作都不允许
let obj1 = {
name: 'jack '
}
//使用对象密封
Object.seal(obj1)
//密封会导致不可扩展
console.log(Object.isExtensible(obj1)) //false
//判断是否密封
console.log(Object.isSealed(obj1)) //true
obj1.age = 18 //无效
obj1.name = 'tom' //改
console.log('name' in obj1) //查询
delete obj1.name //无效
console.log(obj1)
//冻结 只能查询
let obj2 = {
name: 'jack '
}
//冻结对象 只能执行查询操作
Object.freeze(obj2)
//冻结会导致密封
console.log(Object.isSealed(obj2)) //true
//判断是否冻结
console.log(Object.isFrozen(obj2)) //true
obj2.age = 18 //无效
obj2.name = 'tom' //无效
console.log('name' in obj2) //查询
delete obj2.name //无效
console.log(obj2)
属性相关的获取方法 *
- Object.getOwnPropertyNames (获取对象上的所有属性名 ,不包含symbol修饰和原型上的)
- Object.getOwnPropertySymbols (获取对象上名字为symbol的属性名,不包含原型上的)
- Object.getOwnPropertyDescriptor (获取对应的属性的详情对象 ,不包含原型上的)
- Object.getOwnPropertyDescriptors (获取所有的属性的详情对象 ,不包含原型上的)
function Person() {
this.name = 'jack'
}
Person.prototype.age = 18
Person.prototype[Symbol('原型上的')] = 'hello'
let person = new Person()
person[Symbol('对象中的')] = 'world'
person.sex = '男'
let names = Object.getOwnPropertyNames(person)
console.log(names); //['name', 'sex']
let symbols = Object.getOwnPropertySymbols(person)
console.log(symbols); //[Symbol(对象中的)]
let descriptor = Object.getOwnPropertyDescriptor(person, 'name')
console.log(descriptor);
//{value: 'jack', writable: true, enumerable: true, configurable: true}
let descriptors = Object.getOwnPropertyDescriptors(person)
console.log(descriptors); //{name: {…}, sex: {…}, Symbol(对象中的): {…}}
属性对象 (descriptor 对象)
【属性属性】
- configable 是否可以删除
- enumerable 是否可以枚举
- value 值
- writable 是否可以修改
【性访问器属】
- configable 是否可以删除
- enumerable 是否可以枚举
- get 相当于getter方法,访问的时候调用
- set 相当于setter方法,设置的时候调用
Object.defineProperty 用于定义对象的属性 (vue2的底层实现)*
实现数据驱动,也就是数据劫持(vue2中用于双向数据绑定)
let obj = {}
//传入对象,传入属性,传入属性对象
Object.defineProperty(obj, 'name', {
configurable: false, //无法删除
enumerable: false, //无法枚举、遍历
value: 'tom',
writable: false //无法修改
})
console.log(obj); //{name: 'tom'}
obj.name = 'mary'
for (var key in obj) {
console.log(key);
}
delete obj.name
console.log(obj); //{name: 'tom'}
//访问器属性方法,利用数据来驱动页面变化
let _obj = {}
Object.defineProperty(obj, 'age', {
configurable: false, //无法删除
enumerable: false, //无法枚举、遍历
get() {
console.log(1);
return _obj.age
},
set(value) {
//先调用set
console.log(2);
_obj.age = value
}
})
obj.age = 11
console.log(obj);
Object.defineProperties 用于定义对象的多个属性 *
let obj1 = {}
let _obj1 = {}
Object.defineProperties(obj1, {
name: {
value: '蜡笔小新',
configurable: false, //无法删除
enumerable: false, //无法枚举、遍历
writable: false //无法修改
},
age: {
onfigurable: false, //无法删除
enumerable: false, //无法枚举、遍历
get() {
console.log(1);
return _obj1.age
},
set(value) {
//先调用set
console.log(2);
_obj1.age = value
}
}
})
obj1.age = 55
console.log(obj1);
面试题
for in 和 Object.keys 和 Object.getOwnPropertyNames的区别
- for in 包含继承的属性及自身的属性 (不包含不可枚举的、symbol修饰的,包含原型上的和继承的属性)
- Object.keys 只包含自身的属性 (不包含继承、不可枚举、symbol修饰的、原型上的属性)
- Object.getOwnPropertyNames 只包含自身的属性 (不包含继承、原型上和symbol修饰的,包含不可枚举的)
- 三个内容都不包含symbol的属性