查看一个对象的属性和方法的最佳方式:在浏览器输入这行代码
Object.getOwnPropertyNames(Object).sort().forEach(function (val) {console.log(val, '\n')});(2)Object.create()\new object()\{} 三个的区别
Object.create(proto[, propertiesObject])
记住:如果proto参数不是 null 或一个对象,则抛出一个 TypeError 异常。
比如:console.log(Object.create()) // 抛出一个 TypeError 异常Object.create(生成操作)使用指定的原型对象及其属性去创建一个新的对象
var o2 = Object.create({}, {
p: {
value: 42
}
})
o2.p = 10
console.log(o2) // {p: 42}
o2.q = 12
for (var prop in o2) {
console.log(prop) // q
}
delete o2.p // false创建一个可写的,可枚举的,可配置的属性
var o2 = Object.create({}, {
p: {
value: 42,
writable: true,
enumerable: true,
configurable: true
}
})
o2.p = 10 // 可写
console.log(o2) // {p: 10}
o2.q = 12
for (var prop in o2) {
console.log(prop) // p 1 可枚举
}
delete o2.p // true //可配置区别:
Object.create(null) 创建的对象是一个空对象,在该对象上没有继承 Object.prototype 原型链上的属性或者方法,例如:toString(), hasOwnProperty()等方法。
Object.create();继承指定对象
new Object():继承内置对象Object
Object.create = function (obj) {
return { '__proto__': obj};
}
// 视为Object.create实现原理可以通过Object.create(null) 创建一个干净的对象,也就是没有原型,而 new Object() 创建的对象是 Object的实例,原型永远指向Object.prototype
var test1 = {x:1}; // 默认是可读的,可写的,可枚举的,可配置的属性
var test2 = new Object({x:1});
var test3 = Object.create({x:1});
var test4 = Object.create(null);
console.log(test1.x) //1
console.log(test1.__proto__.x === test1.x) //false
console.log(test2.__proto__.x === test1.x) //false
console.log(test3.__proto__.x === test1.x) //true
console.log(test4.__proto__) // undefined
var obj = {}
var obj2 = Object.create(obj)
console.log(obj.__proto__ === Object.prototype) // true
console.log(obj2.__proto === Object.prototype) // false
console.log(obj2.__proto === obj.prototype) //true
//使用现有的对象obj来提供新创建obj2 的对象的__proto__
//简单的说就是重写obj2 的原型(3)Object.defineProperty:在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象。默认可读,可写,可配置,可枚举。数据劫持操作(监控属性变化)(这玩意就很重要了)
Object.defineProperty(obj, prop, descriptor)var obj = {}
Object.defineProperty(obj,"age",{
value: 42,
enumerable: true,
configurable: true ,
set(){},
get(){}
})
注意: value,writable 和 set(){},get(){} 不能同时使用Object.defineProperty缺点:只能监控"对象属性"的改变,监控数组需另行处理,而且对象新增属性也无法有效监控。后续处理,等待vue源码吧。。。
(4) __proto__ \Object.setPrototypeOf()\Object.getPrototypeOf()
对指定对象的原型的一些操作
var obj = {}
var obj = new Object()
console.log(obj.__proto__ === Object.prototype) // true
console.log(Object.getPrototypeOf(obj) === Object.prototype) //true
console.log(obj.constructor.prototype === Object.prototype) //true
实质就是对象的隐示原型 === 实例化对象的构造函数的显示原型function Parent() {
}
var child = new Parent();
console.log(Object.getPrototypeOf(child) === Parent.prototype) // true
Object.setPrototypeOf(child, Object.prototype);
child对象的原型对象设置为Object.prototype对象
console.log(Object.getPrototypeOf(child) === Parent.prototype) // false
function C(){
this.age=4;
}
let proto = {
url:"xxx"
};
C.prototype.address="修改原型对象";
let A=new C();
let B=new C();
Object.setPrototypeOf(A, proto);
console.log(A.address); // undefined
console.log(B.address); // 修改原型对象
console.log(C.prototype.isPrototypeOf(B)) //true
//A,B实例化原型同时指向C
//A的原型对象发生了修改,但是不会影响B的原型对象
//对象B是否在对象C的原型链上Object.setPrototypeOf方法的作用与__proto__相同。用来设置一个对象的prototype对象。它是 ES6 正式推荐的设置原型对象的方法。这里
(5)Object.getOwnPropertyDescriptor:返回指定对象上一个自有属性对应的属性描述符(自身的属性,而不是原型链上的属性)
propertyIsEnumerable() 方法返回一个布尔值,表明指定的属性名是否是当前对象可枚举的自身属性。
var obj = {name:"hello"} // 默认是可枚举,可写,可配置
console.log(Object.getOwnPropertyDescriptor(obj,'name'))
//{value: "hello", writable: true, enumerable: true, configurable: true}
Object.defineProperty(obj,'age',{value:"xxxx"}) // // 默认是不可枚举,不可写,不可配置
console.log(Object.getOwnPropertyDescriptor(obj,'age'))
//{value: "xxxx", writable: false, enumerable: false, configurable: false}var obj = {name:"hello"}
console.log(obj.propertyIsEnumerable('name')) // true(6)for in,Object.keys和Object.getOwnPropertyNames
Object.getOwnPropertyNames:获取对象自身的全部属性名(返回数组:自身所有)
Object.keys:获取对象自身可枚举的属性键(返回数组:自身可枚举的)
for in : 输出自身以及原型链上可枚举的属性。
hasOwnProperty: 输出对象自身的属性
可以这么认为:Object.getOwnPropertyNames就是for in和hasOwnProperty的集合体。
for (var key in child) {
if (child.hasOwnProperty(key)) {
console.log(key);
}
}(7)isPrototypeOf()\instanceOf
isPrototypeOf() 一个对象是否存在于另一个对象的原型链上。
typeof:只能判断:string,boolean,number,NaN,undefined
instanceof: 判断一个实例对象是否由某个构造函数构造而来 ,基于原型链。
constructor:判断一个实例对象是由哪个构造函数构造出来,原型对象被重写会发生变化。
Object.prototype.toString.call(a) === '[object Array]':判断类型的最佳方式
Object.hasOwnPrototype() / in :hasOwnPrototype
var o =new Object();
o.prop ='exists';
console.log(o.hasOwnProperty('prop')) // true
console.log(o.hasOwnProperty('toString')) // false
console.log(o.hasOwnProperty('hasOwnProperty')) //false
console.log('hasOwnProperty' in o) // true
console.log('toString' in o) //true
console.log('prop' in o) //truefunction Person () {}
var person = new Person()
console.log(person.constructor) //Person
console.log(person.constructor === Person) // true
console.log(person instanceof Person) // true
所以:
A.isPrototypeOf (B) 判断的是A对象是否存在与B对象的原型链之中
A instanceof B 判断的是B.prototype是否存在与A的原型链之中
所以就有下面的结论:
如果 A.isPrototypeOf(B) 返回true 则B instanceof A 一定返回true每个函数都有一个原型对象,默认的时候这个原型对象都会得到一个构造函数,这个constructor构造函数指向原型对象所对应的函数(原型指向的函数)。这里
(8) Object.is(A,B)方法用来判断两个值是否相同,类似 ===
特殊点:
console.log(Object.is(+0,-0)) // false
console.log(+0 === -0) // true
console.log(Object.is(NaN,NaN )) // true
console.log(NaN === NaN) // false(9)Object.assign()能够将一个或者多个对象的属性拷贝到目标对象这里
只会拷贝源对象自身的并且可枚举的属性到目标对象。
后来的源的属性将覆盖早先的相同的属性。
object.assign()顶级是深拷贝,其他是浅拷贝。官方列出的例子
let obj1 = { a: 0 , b: { c: 0}};
let obj2 = Object.assign({}, obj1);
console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}
// 检验顶级深拷贝
obj1.a = 1;
console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}
console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}
// 非顶级浅拷贝
obj2.b.c = 3;
console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 3}}
console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 3}}
简单的解决方案: JSON.parse(JSON.stringify(xxx));最好的处理方式终结版
总结:
没有了总结,真正学会了Object吗。。。。。。