Object 構造函數的方法

Object.assign() (es6)

用於將全部可枚舉屬性的值從一個或多個源對象複製到目標對象。它將返回目標對象。es6

Object.assign(target, ...sources) // target 目標對象。 sources 源對象。數組

'use strict';

    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.a = 2;
    console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}
    console.log(JSON.stringify(obj2)); // { a: 2, 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}}
    
    
    //合併對象
    
    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 }
    console.log(o1);  // { a: 1, b: 2, c: 3 },     注意目標對象自身也會改變。
    
    //合併具備相同屬性的對象
    var o1 = { a: 1, b: 1, c: 1 };
    var o2 = { b: 2, c: 2 };
    var o3 = { c: 3 };

    var obj = Object.assign({}, o1, o2, o3);
    console.log(obj); // { a: 1, b: 2, c: 3 }
    
    //拷貝 symbol 類型的屬性
    var o1 = { a: 1 };
    var o2 = { [Symbol('foo')]: 2 };

    var obj = Object.assign({}, o1, o2);
    console.log(obj); // { a : 1, [Symbol("foo")]: 2 } (cf. bug 1207182 on Firefox)
    Object.getOwnPropertySymbols(obj); // [Symbol(foo)]
    
    //繼承屬性和不可枚舉屬性是不能拷貝的
    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__。dom

Object.create(proto, [propertiesObject])函數

proto

新建立對象的原型對象。this

propertiesObject

可選。若是沒有指定爲 undefined,則是要添加到新建立對象的可枚舉屬性(即其自身定義的屬性,而不是其原型鏈上的枚舉屬性)對象的屬性描述符以及相應的屬性名稱。這些屬性對應Object.defineProperties()的第二個參數。spa

//用 Object.create實現類式繼承
    // Shape - 父類(superclass)
    function Shape() {
      this.x = 0;
      this.y = 0;
    }
    
    // 父類的方法
    Shape.prototype.move = function(x, y) {
      this.x += x;
      this.y += y;
      console.info('Shape moved.');
    };
    
    // Rectangle - 子類(subclass)
    function Rectangle() {
      Shape.call(this); // call super constructor.
    }
    
    // 子類續承父類
    Rectangle.prototype = Object.create(Shape.prototype);
    Rectangle.prototype.constructor = Rectangle;
    
    var rect = new Rectangle();
    
    console.log('Is rect an instance of Rectangle?',
      rect instanceof Rectangle); // true
    console.log('Is rect an instance of Shape?',
      rect instanceof Shape); // true
    rect.move(1, 1); // Outputs, 'Shape moved.'
    
    //使用 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() 和 Object.defineProperties()

直接在一個對象上定義新的屬性或修改現有屬性,並返回該對象。prototype

configurable enumerable  value   writable    get     set
數據描述符   Yes         Yes         Yes     Yes          No     No
存取描述符   Yes         Yes         No      No           Yes    Yes
若是一個描述符不具備value,writable,get 和 set 任意一個關鍵字,那麼它將被認爲是一個數據描述符。若是一個描述符同時有(value或writable)和(get或set)關鍵字,將會產生一個異常。
// 顯式
Object.defineProperty(obj, "key", {
  enumerable: false,
  configurable: false,
  writable: false,
  value: "static"
});


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

Object.entries()

返回一個給定對象自身可枚舉屬性的鍵值對數組,其排列與使用 for...in 循環遍歷該對象時返回的順序一致(區別在於 for-in 循環也枚舉原型鏈中的屬性)。code

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

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

// array like object with random key ordering
const anObj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.entries(anObj)); // [ ['2', 'b'], ['7', 'c'], ['100', 'a'] ]

// getFoo is property which isn't enumerable
const myObj = Object.create({}, { getFoo: { value() { return this.foo; } } });
myObj.foo = 'bar';
console.log(Object.entries(myObj)); // [ ['foo', 'bar'] ]

// non-object argument will be coerced to an object
console.log(Object.entries('foo')); // [ ['0', 'f'], ['1', 'o'], ['2', 'o'] ]

// iterate through key-value gracefully
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"
}
// Or, using array extras
Object.entries(obj).forEach(([key, value]) => {
console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
});


// 將Object轉換爲Map

var obj = { foo: "bar", baz: 42 }; 
var map = new Map(Object.entries(obj));
console.log(map); // Map { foo: "bar", baz: 42 }

Object.freeze()

能夠凍結一個對象,凍結指的是不能向這個對象添加新的屬性,不能修改其已有屬性的值,不能刪除已有屬性,以及不能修改該對象已有屬性的可枚舉性、可配置性、可寫性。也就是說,這個對象永遠是不可變的。該方法返回被凍結的對象。對象

const object1 = {
  property1: 42
};

const object2 = Object.freeze(object1);

object2.property1 = 33;
// Throws an error in strict mode

console.log(object2.property1);
// expected output: 42


// 凍結數組
let a = [0];
Object.freeze(a); // The array cannot be modified now.

Object.isFrozen()

判斷對象是否已經凍結。繼承

// 一個對象默認是可擴展的,因此它也是非凍結的.
Object.isFrozen({}); // === false

// 一個不可擴展的空對象同時也是一個凍結對象.
var vacuouslyFrozen = Object.preventExtensions({});
Object.isFrozen(vacuouslyFrozen) //=== true;

// 一個非空對象默認也是非凍結的.
var oneProp = { p: 42 };
Object.isFrozen(oneProp) //=== false

// 讓這個對象變的不可擴展,並不意味着這個對象變成了凍結對象,
// 由於p屬性仍然是能夠配置的(並且可寫的).
Object.preventExtensions(oneProp);
Object.isFrozen(oneProp) //=== false

// ...若是刪除了這個屬性,則它會成爲一個凍結對象.
delete oneProp.p;
Object.isFrozen(oneProp) //=== true

Object.getOwnPropertyDescriptor()

返回指定對象上一個自有屬性對應的屬性描述符。(自有屬性指的是直接賦予該對象的屬性,不須要從原型鏈上進行查找的屬性)

Object.getOwnPropertyDescriptor(obj, prop) //obj 須要查找的目標對象 prop 目標對象內屬性名稱(String類型)
var o, d;

o = { get foo() { return 17; } };
d = Object.getOwnPropertyDescriptor(o, "foo");
// d {
//   configurable: true,
//   enumerable: true,
//   get: /*the getter function*/,
//   set: undefined
// }

o = { bar: 42 };
d = Object.getOwnPropertyDescriptor(o, "bar");
// 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");
// d {
//   value: 8675309,
//   writable: false,
//   enumerable: false,
//   configurable: false
// }

Object.getOwnPropertyNames(obj)

返回一個由指定對象的全部自身屬性的屬性名(包括不可枚舉屬性但不包括Symbol值做爲名稱的屬性)組成的數組。

// 使用Array.forEach輸出屬性名和屬性值
Object.getOwnPropertyNames(obj).forEach(function(val, idx, array) {
  console.log(val + " -> " + obj[val]);
});
//不可枚舉屬性
var my_obj = Object.create({}, {
  getFoo: {
    value: function() { return this.foo; },
    enumerable: false
  }
});
my_obj.foo = 1;

console.log(Object.getOwnPropertyNames(my_obj).sort()); // ["foo", "getFoo"]

//該方法不會獲取到原型鏈上的屬性
function ParentClass() {}
ParentClass.prototype.inheritedMethod = function() {};

function ChildClass() {
  this.prop = 5;
  this.method = function() {};
}

ChildClass.prototype = new ParentClass;
ChildClass.prototype.prototypeMethod = function() {};

console.log(
  Object.getOwnPropertyNames(
    new ChildClass()  // ["prop", "method"]
  )
);

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(value1, value2);

判斷兩個值是不是相同的值。

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

Object.is('foo', 'bar');     // false
Object.is([], []);           // false

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

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

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

Object.preventExtensions(obj)

讓一個對象變的不可擴展,也就是永遠不能再添加新的屬性。

// Object.preventExtensions將原對象變的不可擴展,而且返回原對象.
var obj = {};
var obj2 = Object.preventExtensions(obj);
obj === obj2;  // true
 
// 字面量方式定義的對象默認是可擴展的.
var empty = {};
Object.isExtensible(empty) //=== true
 
// ...但能夠改變.
Object.preventExtensions(empty);
Object.isExtensible(empty) //=== false
 
// 使用Object.defineProperty方法爲一個不可擴展的對象添加新屬性會拋出異常.
var nonExtensible = { removable: true };
Object.preventExtensions(nonExtensible);
Object.defineProperty(nonExtensible, "new", { value: 8675309 }); // 拋出TypeError異常
 
// 在嚴格模式中,爲一個不可擴展對象的新屬性賦值會拋出TypeError異常.
function fail()
{
  "use strict";
  nonExtensible.newProperty = "FAIL"; // throws a TypeError
}
fail();
 
// 一個不可擴展對象的原型是不可更改的,__proto__是個非標準魔法屬性,能夠更改一個對象的原型.
var fixed = Object.preventExtensions({});
fixed.__proto__ = { oh: "hai" }; // 拋出TypeError異常

Object.isExtensible(obj)

判斷一個對象是不是可擴展的(是否能夠在它上面添加新的屬性)。

默認狀況下,對象是可擴展的:便可覺得他們添加新的屬性。以及它們的 proto 屬性能夠被更改。Object.preventExtensions,Object.seal 或 Object.freeze 方法均可以標記一個對象爲不可擴展(non-extensible)。

// 新對象默認是可擴展的.
var empty = {};
Object.isExtensible(empty); // === true

// ...能夠變的不可擴展.
Object.preventExtensions(empty);
Object.isExtensible(empty); // === false

// 密封對象是不可擴展的.
var sealed = Object.seal({});
Object.isExtensible(sealed); // === false

// 凍結對象也是不可擴展.
var frozen = Object.freeze({});
Object.isExtensible(frozen); // === false

Object.seal()

封閉一個對象,阻止添加新屬性並將全部現有屬性標記爲不可配置。當前屬性的值只要可寫就能夠改變。

var obj = {
  prop: function() {},
  foo: 'bar'
};

// New properties may be added, existing properties
// may be changed or removed.
obj.foo = 'baz';
obj.lumpy = 'woof';
delete obj.prop;

var o = Object.seal(obj);

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

// Changing property values on a sealed object
// still works.
obj.foo = 'quux';

// But you can't convert data properties to accessors,
// or vice versa.
Object.defineProperty(obj, 'foo', {
  get: function() { return 'g'; }
}); // throws a TypeError

// Now any changes, other than to property values,
// will fail.
obj.quaxxor = 'the friendly duck';
// silently doesn't add the property
delete obj.foo;
// silently doesn't delete the property

// ...and in strict mode such attempts
// will throw TypeErrors.
function fail() {
  'use strict';
  delete obj.foo; // throws a TypeError
  obj.sparky = 'arf'; // throws a TypeError
}
fail();

// Attempted additions through
// Object.defineProperty will also throw.
Object.defineProperty(obj, 'ohai', {
  value: 17
}); // throws a TypeError
Object.defineProperty(obj, 'foo', {
  value: 'eit'
}); // changes existing property value

Object.isSealed()

判斷一個對象是否被密封。

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

// 若是你把一個空對象變的不可擴展,則它同時也會變成個密封對象.
Object.preventExtensions(empty);
Object.isSealed(empty); // === true

// 但若是這個對象不是空對象,則它不會變成密封對象,由於密封對象的全部自身屬性必須是不可配置的.
var hasProp = { fee: "fie foe fum" };
Object.preventExtensions(hasProp);
Object.isSealed(hasProp); // === false

// 若是把這個屬性變的不可配置,則這個對象也就成了密封對象.
Object.defineProperty(hasProp, "fee", { configurable: false });
Object.isSealed(hasProp); // === true

// 最簡單的方法來生成一個密封對象,固然是使用Object.seal.
var sealed = {};
Object.seal(sealed);
Object.isSealed(sealed); // === true

// 一個密封對象同時也是不可擴展的.
Object.isExtensible(sealed); // === false

// 一個密封對象也能夠是一個凍結對象,但不是必須的.
Object.isFrozen(sealed); // === true ,全部的屬性都是不可寫的
var s2 = Object.seal({ p: 3 });
Object.isFrozen(s2); // === false, 屬性"p"可寫

var s3 = Object.seal({ get p() { return 0; } });
Object.isFrozen(s3); // === true ,訪問器屬性不考慮可寫不可寫,只考慮是否可配置

Object.keys(obj)

返回一個由一個給定對象的自身可枚舉屬性組成的數組,數組中屬性名的排列順序和使用 for...in 循環遍歷該對象時返回的順序一致 。

// 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']

Object.values(obj)

返回一個給定對象本身的全部可枚舉屬性值的數組,值的順序與使用for...in循環的順序相同 ( 區別在於 for-in 循環枚舉原型鏈中的屬性 )。

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

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

// array like object with random key ordering
// when we use numeric keys, the value returned in a numerical order according to the keys
var an_obj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.values(an_obj)); // ['b', 'c', 'a']

// getFoo is property which isn't enumerable
var my_obj = Object.create({}, { getFoo: { value: function() { return this.foo; } } });
my_obj.foo = 'bar';
console.log(Object.values(my_obj)); // ['bar']

// non-object argument will be coerced to an object
console.log(Object.values('foo')); // ['f', 'o', 'o']

Object.setPrototypeOf(obj, prototype)

設置一個指定的對象的原型 ( 即, 內部[[Prototype]]屬性)到另外一個對象或 null

var dict = Object.setPrototypeOf({}, null);
相關文章
相關標籤/搜索