Javascript -- 精通Object对象

191 阅读6分钟

几乎所有的Javascript对象都是Object的实例;一个典型的对象继承了Object.prototype的属性(包括方法),尽管这些属性可能被遮盖。

new Object和Object.create的区别,当传入null参数时,Object.create会返回一个没有原型的东东,而new Object则会返回__proto__

属性

Object.prototype
表示Object的原型对象

Object.prototype.constructor
所有对象会从它的原型上继承一个constuctor,如果直接在控制台打印这个属性,会得到

ƒ Object() { [native code] }

另外有一个值得讨论的方法instanceof,先上例子

var a = {}; 
a.constructor === Object  // true
a instanceof Object       // true

var a = [];
a.constructor === Array   // true
a instanceof Array        // true

var a = 123;
a.constuctor === Number   // true
a instanceof Number       // false

var a = 'abc';
a.constructor === String  // true
a instanceof String       // false
var b = new String('abc')
b instanceof String       // true

var a = true;
a.constructor === Boolean // true
a instanceof Boolean      // false

这些例子,如果是直接用等于号赋值的基本类型字符串、布尔、数字,则比较构造函数时,constructor返回true,instanceof返回false(除非变量通过new来赋值,则也返回true),如果是复杂类型Object或者Array,则两者都相同

方法

Object.assign
方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象,它将返回目标对象。会使用源对象的[[Get]]和目标对象的[[Set]],所以它会调用相关的getter和setter。String类型和Symbol类型的属性都会被拷贝。

Object.assign(target, ...sources)  

var o1 = { a: 1 };
var o2 = { b: 2 };
var o3 = { c: 3 };

var obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }

继承属性和不可枚举属性是不能拷贝的

var obj = Object.create({foo: 1}, { // foo 是个继承属性。
    bar: {
        value: 2  // bar 是个不可枚举属性。
    },
    baz: {
        value: 3,
        enumerable: true  // baz 是个自身可枚举属性。
    }
});

var copy = Object.assign({}, obj);
console.log(copy); // { baz: 3 }

原始类型会被包装为对象

var v1 = "abc";
var v2 = true;
var v3 = 10;
var v4 = Symbol("foo")

var obj = Object.assign({}, v1, null, v2, undefined, v3, v4); 
// 原始类型会被包装,null 和 undefined 会被忽略。
// 注意,只有字符串的包装对象才可能有自身可枚举属性。
console.log(obj); // { "0": "a", "1": "b", "2": "c" }

Object.create
方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__,返回一个新对象,带着指定的原型对象和属性。如果proto参数不是 null 或一个对象,则抛出一个 TypeError 异常。

Object.create(proto, [propertiesObject])
  • proto 新创建对象的原型对象
  • propertiesObject 可选。如果没有指定为 undefined,则是要添加到新创建对象的可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)对象的属性描述符以及相应的属性名称。这些属性对应Object.defineProperties()的第二个参数。

Object.defineProperties
方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象。

  • obj 在其上定义或修改属性的对象
  • props 要定义其可枚举属性或修改的属性描述符的对象。对象中存在的属性描述符主要有两种:数据描述符和访问器描述符(更多详情,请参阅Object.defineProperty())。

Object.defineProperty
方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。

Object.defineProperty(obj, prop, descriptor)

默认情况下,使用 Object.defineProperty() 添加的属性值是不可修改的。

Object.entries
ie不支持,方法返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for...in 循环遍历该对象时返回的顺序一致(区别在于 for-in 循环也枚举原型链中的属性)。

Object.entries(obj)

Object.freeze
方法可以冻结一个对象,冻结指的是不能向这个对象添加新的属性,不能修改其已有属性的值,不能删除已有属性,以及不能修改该对象已有属性的可枚举性、可配置性、可写性。该方法返回被冻结的对象。

Object.freeze(obj)

Object.fromEntries
只有63版本的火狐和Android火狐支持,把键值对列表转换为一个对象。

Object.fromEntries(iterable);  
  • iterable 类似实现了可迭代协议 Array 或者 Map 或者其它对象的可迭代对象。

返回一个包含提供的可迭代对象条目的对应属性的新对象。

const map = new Map([ ['foo', 'bar'], ['baz', 42] ]);
const obj = Object.fromEntries(map);
console.log(obj); // { foo: "bar", baz: 42 }

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

Object.getOwnPropertyDescriptor
方法返回指定对象上一个自有属性对应的属性描述符。

Object.getOwnPropertyDescriptor(obj, prop)
  • obj 需要查找的目标对象
  • prop 目标对象内属性名称(String类型)

Object.getOwnPropertyNames
方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。本身不包含对象的 Symbol 属性,只包含字符串属性。

Object.getOwnPropertyNames(obj)  

Object.getOwnPropertySymbols
方法返回一个给定对象自身的所有 Symbol 属性的数组。

Object.getOwnPropertySymbols(obj)  

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

Object.getPrototypeOf(object)  

直接上例子

const prototype1 = {};
const object1 = Object.create(prototype1);

console.log(Object.getPrototypeOf(object1) === prototype1);
// expected output: true

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

Object.getPrototypeOf(Object) 不是 Object.prototype

Object.getPrototypeOf( Object ) === Function.prototype;        // true

Object.is
ie不支持,方法判断两个值是否是相同的值。

Object.is(value1, value2);  

看看例子

Object.is([], []);           // false

var test = { a: 1 };
Object.is(test, test);       // true  

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

Object.isExtensible
方法判断一个对象是否是可扩展的(是否可以在它上面添加新的属性)。

Object.isExtensible(obj)  

Object.isFrozen
方法判断一个对象是否被冻结

Object.isFrozen(obj)  

Object.isFrozen(1);
// TypeError: 1 is not an object (ES5 code)

Object.isFrozen(1);
// true                          (ES2015 code)

Object.isSealed
方法判断一个对象是否被密封

Object.isSealed(obj)  

例子请看:

// 新建的对象默认不是密封的.
var empty = {};
Object.isSealed(empty); // === false

// 如果你把一个空对象变的不可扩展,则它同时也会变成个密封对象.
Object.preventExtensions(empty);
Object.isSealed(empty); // === true

// 如果把这个属性变的不可配置,则这个对象也就成了密封对象.
Object.defineProperty(hasProp, "fee", { configurable: false });
Object.isSealed(hasProp); // === true

Object.keys
方法会返回一个由一个给定对象的自身可枚举属性组成的数组,返回的是一个字符串数组,数组中属性名的排列顺序和使用 for...in 循环遍历该对象时返回的顺序一致 。

// simple array
var arr = ['a', 'b', 'c'];
console.log(Object.keys(arr)); // console: ['0', '1', '2']  

hasOwnProperty
方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性

obj.hasOwnProperty(prop)  

isPrototypeOf
方法用于测试一个对象是否存在于另一个对象的原型链上。

prototypeObj.isPrototypeOf(object)

propertyIsEnumerable
方法返回一个布尔值,表示指定的属性是否可枚举。

Object.setPrototypeOf
方法设置一个指定的对象的原型 ( 即, 内部[[Prototype]]属性)到另一个对象或 null。