Object方法汇总

Object介绍

Object是JavaScript所有对象的父类,其他对象都继承于Object。

Object构造函数为给定值创建一个对象包装器。如果给定值是null或undefined,将会创建一个空对象。

当以非构造函数被调用时,Object相当于new Object()

Object独享的原生方法分为两类:Object本身的方法与Object的实例方法

本身的方法就是定义在Object对象上的方法,通过Object.直接使用

Object的实例方法是定义在Object原型对象Object.prototype上的方法,被Object实例直接使用

Object.prototype

prototype是Object自带的一个属性,是Object的原型,本身也是一个对象,因此也有一些属性和方法

Object.prototype的属性

属性默认值
configurablefalse
enumerablefalse
writablefalse

configurable 决定能否使用delete、能否需改属性特性、或能否修改访问器属性;

enumerable决定对象属性能否通过for - in循环来获取,默认值为false不可循环

writable决定对象属性是否可被修改,默认值false为不可修改

constructor用于指向原型对象的构造函数,可以修改其值来改变原型对象的构造函数

Object.prototype的方法(Object的实例方法)

Object.prototype.valueOf()

Object.prototype.valueOf():返回当前对象对应的值,如下表所示。valueOf()可通过实例直接调用

对象返回值
Array返回数组对象本身。
Boolean布尔值。
Date存储的时间是从 1970 年 1 月 1 日午夜开始计的毫秒数 UTC。
Function函数本身。
Number数字值。
Object对象本身。这是默认情况。
String字符串值。
Math 和 Error 对象没有 valueOf 方法。
console.log([1, 2, 3, 'aa'].valueOf());  //[1, 2, 3, 'aa']
console.log('ssss'.valueOf());   //ssss
console.log(true.valueOf());  //true
console.log(new Date().valueOf());  //1587481454574

Object.prototype.toString()

Object.prototype.toString()是返回一个对象的字符串形式

Object的toSting()方法并没有什么实际用途,但是实例自定义的方法,如字符串、数组等自定义的toSting()方法能够得到实例转换成字符串的形式

返回的都是字符串

console.log(new Object().toString());  //[object Object]
console.log([1, 2, 3, 'aa'].toString());  //1,2,3,aa
console.log('ssss'.toString());   //ssss
console.log(true.toString());  //true
console.log(new Date().toString());  //Tue Apr 21 2020 23:25:55 GMT+0800 (中国标准时间)
Object.prototype.toString.call()——面试常考题

console.log(new Object().toString()); //[object Object]中返回的后一个Object是指定的该值的构造函数,因此根据这个方法可以用于判断数据类型的方法。但是实例对象自定义的toString()方法会覆盖Object.prototype.toString方法,因此需要使用call来改变this,通过Object.prototype.toString.call()方法可以判断值的类型。

console.log(new Object().toString());  //[object Object]
console.log(Object.prototype.toString.call([1, 2, 3, 'aa']));  //[object Array]
console.log(Object.prototype.toString.call('ssss'));   //[object String]
console.log(Object.prototype.toString.call(true));  //[object Boolean]
console.log(Object.prototype.toString.call(new Date()));  //[object Date]
类型返回值
数值[object Number]
字符串[object String]
布尔值[object Boolean]
undefined[object Undefined]
null[object Null]
数组[object Array]
arguments对象[object Argument]
函数[object Function]
Error对象[object Error]
Date对象[object Date]
RegExp对象[object RegExp]
其他对象[object Object]

Object.prototype.hasOwnProperty()

Object.prototype.hasOwnProperty():该方法会返回一个布尔值,指定对象自身属性中是否存在指定的属性,并且这个属性是非原型链上继承的,in运算符会获取从原型链上继承的属性。只要有该属性便返回true,即使该属性值为null或undefined

let person = {
	name: 'simon',
	age: 24,
    job: undefined,
    girlFriend: null
};
console.log(person.hasOwnProperty('name'));  //true
console.log(person.hasOwnProperty('job')); //true
console.log(person.hasOwnProperty('girlFriend')); //true
console.log(person.hasOwnProperty('toString'));  //false

Object.prototype.isPrototypeOf()

prototypeobj.isPrototypeOf(object):用于判断object对象是否存在于另外prototyepeobj对象的原型链上,返回一个布尔值。

function Foo() {}
function Bar() {}
function Baz() {}

Bar.prototype = Object.create(Foo.prototype);
Baz.prototype = Object.create(Bar.prototype);

var baz = new Baz();

console.log(Baz.prototype.isPrototypeOf(baz)); // true
console.log(Bar.prototype.isPrototypeOf(baz)); // true
console.log(Foo.prototype.isPrototypeOf(baz)); // true
console.log(Object.prototype.isPrototypeOf(baz)); // true
instanceof运算符

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上,返回一个布尔值。

// 定义构造函数
function C(){} 
function D(){} 

var o = new C();

o instanceof C; // true,因为 Object.getPrototypeOf(o) === C.prototype

o instanceof D; // false,因为 D.prototype 不在 o 的原型链上

o instanceof Object; // true,因为 Object.prototype.isPrototypeOf(o) 返回 true
C.prototype instanceof Object // true,同上

C.prototype = {};
var o2 = new C();

o2 instanceof C; // true

o instanceof C; // false,C.prototype 指向了一个空对象,这个空对象不在 o 的原型链上.

D.prototype = new C(); // 继承
var o3 = new D();
o3 instanceof D; // true
o3 instanceof C; // true 因为 C.prototype 现在在 o3 的原型链上

String对象会出现一些特殊情况

let str = 'aaaaa';
let newStr = new String('aaaa');
console.log(str instanceof String);   //false
console.log(str instanceof Object);   //false
console.log(newStr instanceof String);   //true
console.log(newStr instanceof Object);   //true

Object.prototype.propertyIsEnumerable()

obj.propertyIsEnumerable(prop):判断指定的属性是否可枚举。每个对象都有一个propertyIsEnumerable方法,该方法可以确定对象中指定的属性是否可以被for-in循环枚举。返回一个布尔值。

let obj = {
    prop: 'is Enumerable',
}
obj.propertyIsEnumerable('prop');  //true
let arr = [];
arr[0] = 'is Enumerable too';
arr.propertyIsEnumerable(0);  //true
arr.propertyIsEnumerable('length'); //false
//内置对象
Math.propertyIsEnumerable('random');  //false
this.propertyIsEnumerable('Math'); //false

Object的方法(静态方法)

Object.keys()、Object.getOwnPropertyNames()

Object.keys()、Object.getOwnPropertyNames()都是用于遍历对象的属性

Object.keys(obj)方法的参数是一个对象,并返回一个包含该对象属性的数组。数组中的属性是对象自身的,不是继承的属性。因此该方法返回的是自身的属性

Object.getOwnPropertyNames(obj)方法与Object.keys(obj)类似,参数是一个对象,返回值是一个包含对象属性的数组。并且是该对象本身的,不是继承的属性。

两个方法的区别在于:Object.keys(obj)返回的是可枚举的属性,而Object.getOwnPropertyNames(obj)还可以返回不可枚举的属性

let person = {
	name: 'simon',
	age: 24,
	job: undefined,
	girlFriend: null
};
console.log(Object.keys(person));  // ["name", "age", "job", "girlFriend"]
console.log(Object.getOwnPropertyNames(person));  // ["name", "age", "job", "girlFriend"]
let arr = [1,2,'aaa'];
console.log(Object.keys(arr));  //["0", "1", "2"]
console.log(Object.getOwnPropertyNames(arr));  //["0", "1", "2", "length"]
//通过这两个方法可用于获取对象属性的个数
console.log(Object.keys(person).length);   //4
console.log(Object.getOwnPropertyNames(person).length);  //4

Object.assign()

Object.assign(target, …sources):用于将所有**可枚举属性的值从一个或多个源对象复制到目标对象,并返回目标对象。继承属性和不可枚举数据不能被复制**

如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖,并且后面的源对象也会类似的覆盖前面的源对象属性。

//复制一个对象
const obj = {a:1};
const copy = Object.assign({},obj);
console.log(copy);  //{a:1}

//合并对象
const o1 = { a: 1 };
const o2 = { b: 2 };
const o3 = { c: 3 };
const obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1);  // { a: 1, b: 2, c: 3 }, 由于o1作为目标对象,因此也会发生改变

//合并具有相同属性类型的对象
const o1 = { a: 1, b: 1, c: 1 };
const o2 = { b: 2, c: 2 };
const o3 = { c: 3 };
const obj = Object.assign({}, o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 } 后面的对象中的属性会将前面对象的相同的属性所覆盖

该方法无法用于深拷贝,因为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: 2, b: { c: 3}} 

// Deep Clone 
obj1 = { a: 0 , b: { c: 0}}; 
let obj3 = JSON.parse(JSON.stringify(obj1)); 
obj1.a = 4; 
obj1.b.c = 4; 
console.log(JSON.stringify(obj3)); // { a: 0, b: { c: 0}}

Object.create()

Object.create(obj, [,propertiesObject]):可创建一个拥有指定原型和若干个指定属性的对象。obj是新创建对象的原型对象,propertiesObject是可选参数,默认为undefined。如果有值的话是要添加到新创建对象的不可枚举(默认)属性(即自身的属性,而不是其原型链上的枚举属性)。方法返回一个新对象。

//用 Object.create实现类式继承多个对象
function MyClass() {
     SuperClass.call(this);
     OtherSuperClass.call(this);
}

// 继承一个类
MyClass.prototype = Object.create(SuperClass.prototype);
// 混合其它
Object.assign(MyClass.prototype, OtherSuperClass.prototype);
// 重新指定constructor
MyClass.prototype.constructor = MyClass;

MyClass.prototype.myMethod = function() {
     // do a thing
};
//使用 Object.create 的 propertyObject参数
var o;
// 创建一个原型为null的空对象
o = Object.create(null);

o = {};
// 以字面量方式创建的空对象就相当于:
o = Object.create(Object.prototype);

o = Object.create(Object.prototype, {
  // foo会成为所创建对象的数据属性
  foo: { 
    writable:true,
    configurable:true,
    value: "hello" 
  },
  // bar会成为所创建对象的访问器属性
  bar: {
    configurable: false,
    get: function() { return 10 },
    set: function(value) {
      console.log("Setting `o.bar` to", value);
    }
  }
});

function Constructor(){}
o = new Constructor();
// 上面的一句就相当于:
o = Object.create(Constructor.prototype);
// 当然,如果在Constructor函数中有一些初始化代码,Object.create不能执行那些代码

// 创建一个以另一个空对象为原型,且拥有一个属性p的对象
o = Object.create({}, { p: { value: 42 } })

// 省略了的属性特性默认为false,所以属性p是不可写,不可枚举,不可配置的:
o.p = 24
o.p
//42

o.q = 12
for (var prop in o) {
   console.log(prop)
}
//"q"

delete o.p
//false

//创建一个可写的,可枚举的,可配置的属性p
o2 = Object.create({}, {
  p: {
    value: 42, 
    writable: true,
    enumerable: true,
    configurable: true 
  } 
});

Object.defineProperty()——Vue响应式原理

Object.defineProperty(obj, prop, descriptor)方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象

通过该方法添加的属性是可枚举的,在枚举对象属性时会被枚举到(for-in或Object.keys方法),可以改变这些属性的值,也可以删除这些属性。

属性描述
obj要定义属性的对象
prop要定义或修改的属性的名称
descriptor要定义或修改的属性描述符

对象(prop)中存在两种属性描述符:数据描述符和存取描述符。数据描述符是一个具有值的属性,该值是可写的,也可以是不可写的。存取描述符是由getter函数和setter函数所描述的属性。一个描述符只能是两者之一。

这两种描述符都是对象,并共享以下可选的键值(若不选择则在定义属性时选择默认值),即数据描述符和存取描述符都具有以下四个键值

属性默认值描述
configurablefalse当且仅当该属性的configurable键值为true时,该属性的描述符才能被改变,同时该属性也能从对应的对象上被删除
enumerablefalse当且仅当该属性的enumerable键值为true时,该属性才会出现在对象的枚举属性中(for-in循环和Object.keys()方法)
writablefalse当且仅当该属性的writable键值为true时,属性的值,也就是value,才能被改变。当为false时,value不能被重新赋值
valueundefined该属性对应的值,可以是任何数据类型(数值,对象,函数等)

存取描述符还具有以下可选键值:

get:属性的getter函数,如果没有getter,则为undefined。当访问该属性时,就会默认调用此函数。默认为undefined

set:属性的setter函数,如果没有setter,则为undefined。当属性值被修改时,就会默认调用此函数。该方法会传入一个参数(也就是被赋予的新值)。默认为undefined

描述符可拥有的键值

configurableenumerablevaluewritablegetset
数据描述符可以可以可以可以不可以不可以
存取描述符可以可以不可以不可以可以可以
var o = {}; // 创建一个新对象

// 在对象中添加一个属性与数据描述符的示例
Object.defineProperty(o, "a", {
  value : 37,
  writable : true,
  enumerable : true,
  configurable : true
});

// 对象 o 拥有了属性 a,值为 37

// 在对象中添加一个设置了存取描述符属性的示例
var bValue;
Object.defineProperty(o, "b", {
  // 使用了方法名称缩写(ES2015 特性)
  // 下面两个缩写等价于:
  // get : function() { return bValue; },
  // set : function(newValue) { bValue = newValue; },
  get() { return bValue; },
  set(newValue) { bValue = newValue; },
  enumerable : true,
  configurable : true
});

o.b; // 38
// 对象 o 拥有了属性 b,值为 38
// 现在,除非重新定义 o.b,o.b 的值总是与 bValue 相同

// 数据描述符和存取描述符不能混合使用
Object.defineProperty(o, "conflict", {
  value: 0x9f91102,
  get() { return 0xdeadbeef; } 
});

添加属性的两种方式

var o = {};
o.a = 1;
// 等同于:
Object.defineProperty(o, "a", {
  value: 1,
  writable: true,
  configurable: true,
  enumerable: true
});

// 另一方面,
Object.defineProperty(o, "a", { value : 1 });
// 等同于:
Object.defineProperty(o, "a", {
  value: 1,
  writable: false,
  configurable: false,
  enumerable: false
});

Object.defineProperties()

Object.defineproperties(obj, props)方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象。这个方法与Object.defineProperty()类似,但是可以对一个对象定义多个新的属性

var obj = {};
Object.defineProperties(obj, {
  'property1': {
    value: true,
    writable: true
  },
  'property2': {
    value: 'Hello',
    writable: false
  }
  // etc. etc.
});

Object.entries()

object.entries(obj)方法返回一个数字,其元素是与直接在obj上找到可枚举属性键值对相对应的数组。属性的顺序与for-in循环对象的属性值所给的顺序相同(但是该方法只会返回自身的属性,而不会返回继承的可枚举属性,for-in循环还会枚举原型链中的可枚举属性)

const obj = { foo: 'bar', baz: 42 };
console.log(Object.entries(obj)); // [ ['foo', 'bar'], ['baz', 42] ]

const obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.entries(obj)); // [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ]

const anObj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.entries(anObj)); // [ ['2', 'b'], ['7', 'c'], ['100', 'a'] ]

//使用for-of循环Object.entries()数组
const obj = { a: 5, b: 7, c: 9 };
for (const [key, value] of Object.entries(obj)) {
	console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
}

Object.entries(obj).forEach(([key, value]) => {
	console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
});

Object.freeze()、 Object.isFrozen()

Object.freeze(obj) 方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值,访问器属性(getter和setter)也一样使用。此外,冻结一个对象后该对象的原型也不能被修改。freeze() 返回和传入的参数相同的对象,而不是传递对象的一个被冻结的副本。

Object.isFrozen(obj)用于判断一个对象是否被冻结,返回一个布尔值

//冻结对象
var obj = {
  prop: function() {},
  foo: 'bar'
};

// 新的属性会被添加, 已存在的属性可能会被修改或移除
obj.foo = 'baz';
obj.lumpy = 'woof';
delete obj.prop;

// 作为参数传递的对象与返回的对象都被冻结,所以不必保存返回的对象(因为两个对象全等)
var o = Object.freeze(obj);

o === obj; // true
Object.isFrozen(obj); // === true

// 现在任何改变都会失效
obj.foo = 'quux'; // 静默地不做任何事
// 静默地不添加此属性
obj.quaxxor = 'the friendly duck';

// 试图通过 Object.defineProperty 更改属性,下面两个语句都会抛出 TypeError.
Object.defineProperty(obj, 'ohai', { value: 17 });
Object.defineProperty(obj, 'foo', { value: 'eit' });

// 也不能更改原型,下面两个语句都会抛出 TypeError.
Object.setPrototypeOf(obj, { x: 20 })
obj.__proto__ = { x: 20 }

//冻结数组
let a = [0];
Object.freeze(a); // 现在数组不能被修改了.

//修改无效
a[0]=1; 
a.push(2); 

//被冻结的 对象是不可变的,但是对象里面的对象是可变的,因为被冻结对象里面的对象只是一个引用,函数和数组都是对象
obj1 = {
  internal: {},
  arr: []  
};

Object.freeze(obj1);
obj1.internal.a = 'aValue';
obj1.arr[0] = 1;

console.log(obj1.internal.a);// 'aValue'
console.log(obj1.arr[0]);  //1

Object.getOwnPropertyDescriptor()、Object.getOwnPropertyDescriptors()

Object.getOwnPropertyDescriptor(obj, prop)方法返回指定对象上一个自有属性对应的属性描述符。自有属性是指直接赋予该对象的属性,而不是从原型链上进行查找的属性;

Object.getOwnPropertyDescriptors(obj)方法返回一个对象的所有自身属性的描述符;如果没有任何自身属性,则返回一个空对象

	var o, d;

	o = { get foo() { return 17; } };
	d = Object.getOwnPropertyDescriptor(o, "foo");
	console.log(d);
	// d {
	//   configurable: true,
	//   enumerable: true,
	//   get: /*the getter function*/,
	//   set: undefined
	// }
	o = { bar: 42 };
	d = Object.getOwnPropertyDescriptor(o, "bar");
	console.log(d);
	// d {
	//   configurable: true,
	//   enumerable: true,
	//   value: 42,
	//   writable: true
	// }
	o = {};
	Object.defineProperty(o, "baz", {
		value: 8675309,
		writable: false,
		enumerable: false
	});
	d = Object.getOwnPropertyDescriptor(o, "baz");
	console.log(d);
	// d {
	//   value: 8675309,
	//   writable: false,
	//   enumerable: false,
	//   configurable: false
	// }

Object.getPrototypeOf()

Object.getPrototypeOf(obj)方法返回指定对象的原型(内部[[prototype]]属性的值)

var proto = {};
var obj = Object.create(proto);
Object.getPrototypeOf(obj) === proto; // true

var reg = /a/;
Object.getPrototypeOf(reg) === RegExp.prototype; // true

Object.is()

Object.is(value1,value2)方法判断两个值是否是相同的值,返回一个布尔值

如果下列任何一项成立,则两个值相同(返回true)

  • 两个值都是 undefined
  • 两个值都是 null
  • 两个值都是 true 或者都是false
  • 两个值是由相同个数的字符按照相同的顺序组成的字符串
  • 两个值指向同一个对象
  • 两个值都是数字并且
    • 都是正零 +0
    • 都是负零 -0
    • 都是NaN
    • 都是除零和 NaN 外的其它同一个数字

这个方法与 == 运算符不同,==运算符会将两边的值做隐式转换(若两者类型不同),然后去比较。但是Object.is()不会去做转换

Object.is()与 **===**也不同,===运算符会将+0 和-0视为相等,并认为NaN不等于NaN

Object.is('foo', 'foo');     // true
Object.is(window, window);   // true

Object.is('foo', 'bar');     // false
Object.is([], []);           // false,数组也是对象,但是这两个数组并不是同一个数组

var foo = { a: 1 };
var bar = { a: 1 };
Object.is(foo, foo);         // true
Object.is(foo, bar);         // false,foo和bar不是同一个对象

Object.is(undefined, undefined);       // true
Object.is(null, null);       // true

// 特例
Object.is(0, -0);            // false
Object.is(0, +0);            // true
Object.is(-0, -0);           // true
Object.is(NaN, 0/0);         // true

Object.values()

Object.values(obj)方法返回一个给定对象自身的所有可枚举属性值的数组,值的顺序与使用for-in循环的顺序相同(区别在于for-in会循环原型链上的属性)

这个方法与Object.kyes()方法类似,只不过该方式获取的是属性值,而keys()方法获取的是属性。

而Object.entries()方法获取的是属性和属性值共同组成的数组

var obj = { foo: 'bar', baz: 42 };
console.log(Object.values(obj)); // ['bar', 42]

var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.values(obj)); // ['a', 'b', 'c']

Object.setPrototypeOf()

Object.setPrototypeOf(obj, prototype)方法设置一个指定的对象的原型(即[[prototyoe]]属性)到另外一个对象或null

Object.getOwnPropertyNames()

Object.getOwnPropertyNames(obj)返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组

var arr = ["a", "b", "c"];
console.log(Object.getOwnPropertyNames(arr).sort()); // ["0", "1", "2", "length"]

// 类数组对象
var obj = { 0: "a", 1: "b", 2: "c"};
console.log(Object.getOwnPropertyNames(obj).sort()); // ["0", "1", "2"]

若只需要获取可枚举属性,可以使用Object.keys或用for-in循环并用hasOwnProperty()过滤掉原型链上的可枚举属性

参考: https://javascript.ruanyifeng.com/stdlib/object.html#toc1

​ https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值