我们都知道在js里面一切都是对象,window也是个对象,对象里拥有很多属性和方法,可以了解一下对象。
在控制台打印一下Object对象,console.dir(Object),我们可以看到Object拥有的属性,方法还有原型,其中有一个方法叫getOwnPropertyNames,我们可以利用这个方法去得到Object本身的属性和方法。
现在在控制里输入Object.getOwnPropertyNames(Object)就能够得到Object对象所有自身属性和方法,由于浏览器的兼容性问题,所以在谷歌里面只有23个,ie里有18个,由于本人火狐不常用也就不做测试了,如图所示:
不同的浏览器,所展示的属性和方法个数都不一样,我们以谷歌为准去理解一下哪些不常用又好用的方法,
Object.assign()
Object.assign是ES6新添加的接口,主要的用途是用来合并多个JavaScript的对象。
用法:Object.assign(target,source) target是目标对象,sources是源对象(可以有一个或者多个),将sources源对象中所有可枚举的属性的值复制到目标的对象中,其会返回target对象,还有它接收的第一个参数应该是对象,如果不是对象的话,它会在内部转换成对象,所以如果碰到了null或者undefined这种不能转换成对象的值的话,assign就会报错。举个简单的例子:
let obj = {a: 1, b: 2, c: 3};
let newObj = {};
console.log(Object.assign(newObj, obj)) // {a: 1, b: 2, c: 3}
console.log(newObj === Object.assign(newObj , obj)) // true
从上可以看出obj对象里的属性和值都被复制到了newObj里去了,我们再来看一个例子:
const str = 'abc';
const boo = true;
const num = 10;
const obj = Object.assign({}, str, boo, num);
console.log(obj); // { "0": "a", "1": "b", "2": "c" }
为什么呢?理想中结果应该是{ “0”: “abc”, “1”: true, “2”: 10 }才对,这是因为当字符串转成对象的时候每一个字符都会被当做属性的值,那为什么true和10都没有进来呢?因为它们都是不可枚举的属性,还有它是浅拷贝的,我们再来看一个例子:
const obj1 = {a: {b: 1}};
const obj2 = Object.assign({}, obj1);
obj1.a.b = 2;
console.log(obj2.a.b) // 2
我们改变了obj1的a属性的b的值,而目标对象的b的值也跟着改变了,因为浅拷贝的是对象的属性的引用,而不是对象本身。
该方法的兼容性不是很好,IE全面沦陷,在移动端方面,仅有少数的浏览器才兼容该方法。幸好的是在MDN上提供了兼容的方法。
相关链接:Object.assign
Object.create() 创建对象
Object.create(proto, [propertiesObject ]) 是ES5中提出的一种新的对象创建方式,第一个参数是要继承的原型,如果不是一个子函数,可以传一个null,第二个propertiesObject参数是属性描述符,只能传 null 或一个对象,否则抛出一个 TypeError 异常。举个栗子:
let obj=Object.create(null,{
name:{
value:"pingfan",
enumerable:true
}
});
console.log(obj.name); // pingfan
console.log(obj.__proto__); // undefined
let name = {name: 'fanfan'};
let obj2=Object.create(name,{
name:{
value:"pingfan",
enumerable:true
},
age:{
get () {return this._Age+"岁了";},
set (value) {this._Age = value;}
}
});
console.log(obj2.name); // pingfan
console.log(obj2.__proto__); // {name: "fanfan"}
obj2.age = 4; // 这里执行set方法
console.log(obj2.age); // 这里执行get方法 4岁了
propertiesObject 参数的详细解释:(默认都为false)
1.数据属性
writable:是否可任意写
configurable:是否能够删除,是否能够被修改
enumerable:是否能用 for in 枚举
2.value:值
访问属性:
get(): 访问
set(): 设置
注意:当使用了getter或setter方法,不允许使用writable和value这两个属性
Object.defineProperty()
Object.defineProperty(obj,prop,descriptor) 方法在obj对象上对prop属性进行定义或修改,其中descriptor为被定义或修改的属性符。属性符的操作如上面propertiesObject 参数所示,代码如下:
let obj = {};
let initValue = 'hello';
Object.defineProperty(obj,"newKey",{
get:function (){
return initValue;
},
set:function (value){
initValue = value;
},
configurable: true | false,
enumerable: true | false,
});
console.log(obj.newKey); // hello
obj.newKey = 'pingfan'; // 调用set方法
console.log(obj.newKey); // pingfan
vue的双向数据绑定就是通过Object.defineProperty实现的
相关文档链接:Object.defineProperty
object.defineProperties(object, descriptors)
参数解析:
object:必需,要添加或者修改属性的对象。
descriptors:必需,一个对象直接量,用来设置数据属性或访问器属性的特性,与Object.defineProperty方法不同的是,它既可以设置或者修改一个属性,也可以是多个属性。
代码如下:
let obj = {
name:"pingfan",
url:"shenzhen"
};
Object.defineProperties(obj,{
address:{
value:"深圳市",
writable:true,
numerable:true,
configurable:true
},
age:{
value:2,
writable:true,
numerable:true,
configurable:true
}
});
console.log(obj.address); // 深圳市
console.log(obj.age); // 2
Object.getOwnPropertyDescriptor(object, propertyname)
Object.getOwnPropertyDescriptor(object, propertyname) 通常是用来描述对象的相关特性。
ES5新增此方法。
参数解析:
propertyname:必需,属性名称。
代码如下:
let obj={
name:"pingfan"
}
let descriptor = Object.getOwnPropertyDescriptor(obj,"name");
console.log(descriptor); // {value: "pingfan", writable: true, enumerable: true, configurable: true}
该方法是用于如果propertyname属性存在对象obj上,则返回其属性描述符,如果不存在就返回undefined。该属性描述符由下面的属性所组成。
Object.getOwnPropertyDescriptors
ES8新增方法
Object.getOwnPropertyDescriptors() 方法用来获取一个对象的所有自身属性的描述符。
代码如下:
let obj={
name:"pingfan",
add: 'youyou'
}
let descriptor = Object.getOwnPropertyDescriptors(obj);
console.log(descriptor);
打印如图所示:
Object.getPrototypeOf(obj)
ES5新增此方法。
参数解析:
obj:必需,规定要获取原型的对象。
代码如下:
function Name(){
this.name="pingfan";
}
Name.prototype={
age:3
}
let a = new Name();
console.log(Object.getPrototypeOf(a).age); // 3
该方法返回对象的原型对象,如果没有的话,则返回null。需要指出的是,对于函数对象,其返回的并不是显式原型(prototype),而是隐式原型 (__proto__) ,该方法兼容IE9及以上的浏览器。
Object.is(val1,val2)
ES5 比较两个值是否相等,只有两个运算符:相等运算符(==) 和严格相等运算符(===)。它们都有缺点,前者会自动转换数据类型,后者的NaN不等于自身,以及+0等于-0。 JavaScript 缺乏一种运算,在所有环境中,只要两个值是一样的,它们就应该相等。
ES6 提出 “Same-value equality” (同值相等)算法,用来解决这个问题。Object.is就是部署这个算法的新方法。它用来比较两个值是否严格相等,与严格比较运算符( === )的行为基本一致。
和全等不同之处只有两个:一是+0不等于-0,二是NaN等于自身。
+0 === -0 //true
NaN === NaN // false
Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
Object.is通过defineProperty定义的方法:代码如下:
Object.defineProperty(Object, 'is', {
value: function(x, y) {
if (x === y) {
// 针对 +0 不等于 -0 的情况
return x !== 0 || 1 / x === 1 / y;
}
// 针对 NaN 的情况
return x !== x && y !== y;
},
configurable: true,
enumerable: false,
writable: true
});
Object.preventExtensions()
该方法可以让一个对象永远不能添加新的属性,在严格模式下,如果强行为对象添加属性,会报错,代码如下:
"use strict";
var obj = {name:"zhang"};
obj.name = "li"//可以进行修改
Object.preventExtensions(obj);
Object.isExtensible(obj) //=== false 判断是否可以修改
//obj.age = 14;严格模式下会报错
obj.__proto__.age = 13;
console.log(obj);//能够在原型对象上添加属性
obj.__proto__ = {}//不能直接重定义原型,会报错。
Object.keys(obj)
Object.keys()方法会返回一个由一个给定对象的自身可枚举属性组成的数组。
ES8,ES7新增Object.values(),Object.entries()方法返回一个给定对象中所有可枚举属性值的数组,值的顺序与使用。
代码如下:
// simple array
var arr = ['a', 'b', 'c'];
console.log(Object.keys(arr)); // console: ['0', '1', '2']
// array like object
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.keys(obj)); // console: ['0', '1', '2']
// array like object with random key ordering
var anObj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.keys(anObj)); // console: ['2', '7', '100']
// getFoo is a property which isn't enumerable
var myObj = Object.create({}, {
getFoo: {
value: function () { return this.foo; }
}
});
myObj.foo = 1;
console.log(Object.keys(myObj)); // console: ['foo']