es6 --- 對象的擴展

es6的對象屬性

 

Object.is()     

      用來比較兩個值是否嚴格相等,與嚴格比較運算符( === ) 的行爲基本一致

 

Object.is('foo', 'foo')
// true
Object.is({}, {})
// false

注意::   +0 不等於 -0       NaN等於自身

+0 === -0 //true
NaN === NaN // false

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

Object.assign(a,b,c)

      用於對象合併,將源對象(source)的所有可枚舉屬性,複製到目標對象( target )

      a 是目標對象   b,c是源對象,也是就需要賦值的對象

     注意:  如果目標對象與源對象有同名屬性,或者多個源對象有同名屬性,則後面的屬性會覆蓋前面的屬性

var target = { a: 1, b: 1 };

var source1 = { b: 2, c: 2 };
var source2 = { c: 3 };

Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}

如果只有一個參數,Object.assign()會直接返回這個參數

var obj = {a:1}
Object.assign(obj) === obj

如果該參數不是對象,則會先轉化成對象,然後返回

undefined 和 null 無法轉化成對象,所以用他們作爲參數,就會報錯,但是如果這非對象參數的位置在源對象中,就會跳過這些無法轉化的對象,因此不會報錯.如果在目標對象中,無法跳過,就一定報錯

 

其他類型的值( 即數值 ,字符串 和 布爾值 ) 不在首參數,也不會報錯,但是,除了字符串會以數組的形式拷貝到目標對象,其他值都不會產生效果,會被忽略.

var v1 = 'abc';
var v2 = true;
var v3 = 10;

var obj = Object.assign({}, v1, v2, v3);
console.log(obj); // { "0": "a", "1": "b", "2": "c" }

 

Object.assign()拷貝的屬性是有限制的,只拷貝源對象的自身屬性( 不拷貝繼承屬性) ,也不拷貝不可枚舉的屬性

屬性名爲Symbol值的屬性,會被拷貝

 

注意:   Object.assign() 方法實行的是淺拷貝,  如果遇到同名的屬性,會將其覆蓋起值

 

 

常見的用途:::

       1:       爲對象添加屬性

x屬性和y屬性添加到Point類的對象實例

class Point {
  constructor(x, y) {
    Object.assign(this, {x, y});
  }
}

2:    爲對象添加方法

Object.assign(SomeClass.prototype, {
  someMethod(arg1, arg2) {
    ···
  },
  anotherMethod() {
    ···
  }
});

// 等同於下面的寫法
SomeClass.prototype.someMethod = function (arg1, arg2) {
  ···
};
SomeClass.prototype.anotherMethod = function () {
  ···
};

 3::: 克隆對象

     將原始對象拷貝到一個空對象中,就能得到一個一模一樣的原始對象的克隆對象了

function clone(origin) {
  return Object.assign({}, origin);
}

不過,採用這種克隆,只能克隆原始對象自身的值,不能克隆它繼承的值.如果想要保持繼承鏈,可以採用以下方式:

function clone(origin) {
  let originProto = Object.getPrototypeOf(origin);
  return Object.assign(Object.create(originProto), origin);
}

4::: 合併多個對象

  將多個對象合併到某個對象中去,第一個參數爲目標對象,後面是源對象

const merge =
  (target, ...sources) => Object.assign(target, ...sources);

如果希望合併後返回一個新對象,可以改寫上面函數,對一個空對象合併。

const merge =
  (...sources) => Object.assign({}, ...sources);

5::: 爲屬性指定默認值

 

const DEFAULTS = {
  logLevel: 0,
  outputFormat: 'html'
};

function processContent(options) {
  options = Object.assign({}, DEFAULTS, options);
}

注意::  存在深拷貝的問題

 

屬性的可枚舉性

對象的每個屬性都有一個描述對象,用來控制該屬性的行爲.

Object.getOwnPropertyDescriptor方法可以獲取該屬性的描述對象。

描述對象的enumerable屬性,稱爲'可枚舉性',如果該屬性爲false,就表示某些操作會忽略當前屬性.

以下這幾個操作都會忽略enumerable屬性

   for  ...in  ::  只會遍歷對象自身的和繼承的可枚舉的屬性

    Object.keys()  :: 返回對象自身的所有可枚舉的屬性的鍵名

   JSON.stringify() ::  只串行對象自身的可枚舉的屬性

   Object.assign) ::  只拷貝對象自身的可枚舉的屬性

另外,es6規定,所有的class的原型的方法都是不可枚舉的

 屬性的遍歷

1::  for ... in  循環遍歷對象自身的和繼承的可枚舉屬性( 不包含symbol屬性 )

 

2::  Object.keys()  返回一個數組,包括對象自身的( 不含繼承的 ) 所有可枚舉的屬性( 不含symbol )

 

3:: Object.getOwnPropertyNames(obj) 返回一個數組,包括對象自身的所有屬性( 不含symbol屬性,但是包括不可枚舉屬性)

 

4::  Object.getOwnPropertySymbols(obj) 返回一個數組.包含對象自身的所有symbol屬性

5::  Reflect.ownKeys(obj) 返回一個數組,包含對象自身的所有屬性,不管是屬性名是symbol或者字符串.也不管是否可枚舉

以上的5種方法遍歷對象的屬性,都遵守同樣的屬性遍歷的次序規則。

  • 首先遍歷所有屬性名爲數值的屬性,按照數字排序。
  • 其次遍歷所有屬性名爲字符串的屬性,按照生成時間排序。
  • 最後遍歷所有屬性名爲Symbol值的屬性,按照生成時間排序。

 

_proto_     

如果一個對象本身部署了_proto_屬性,則該屬性的值就是對象的原型

_proto_屬性(前後各兩個下劃線) ,用來讀取或設置當前對象的prototype對象.

它的本質是一個內部屬性,並不是api,只是瀏覽器廣泛支持.而且只有瀏覽器必須部署這個屬性,其他運行環境不一定需要部署,而且新的代碼最好不要使用這個屬性,可以使用Object.setPrototypeOf()  寫操作  , Object.getPrototypeOf()  讀操作 , Object.create()  生成操作

在實現上,__proto__調用的是Object.prototype.__proto__,具體實現如下。

Object.defineProperty(Object.prototype, '__proto__', {
  get() {
    let _thisObj = Object(this);
    return Object.getPrototypeOf(_thisObj);
  },
  set(proto) {
    if (this === undefined || this === null) {
      throw new TypeError();
    }
    if (!isObject(this)) {
      return undefined;
    }
    if (!isObject(proto)) {
      return undefined;
    }
    let status = Reflect.setPrototypeOf(this, proto);
    if (!status) {
      throw new TypeError();
    }
  },
});
function isObject(value) {
  return Object(value) === value;
}

Object.setPrototypeOf() 

用來設置一個對象的prototype對象

// 格式
Object.setPrototypeOf(object, prototype)

// 用法
var o = Object.setPrototypeOf({}, null);
function (obj, proto) {
  obj.__proto__ = proto;
  return obj;
}

Object.getPrototypeOf()

用來讀取一個對象的prototype對象

Object.getPrototypeOf(obj);
function Rectangle() {
}

var rec = new Rectangle();

Object.getPrototypeOf(rec) === Rectangle.prototype
// true

Object.setPrototypeOf(rec, Object.prototype);
Object.getPrototypeOf(rec) === Rectangle.prototype
// false

 

Object.keys()

遍歷屬性的鍵名,返回一個數組,成員是參數對象自身的(不含繼承)所有可以遍歷的(enumerable)

var obj = { foo: "bar", baz: 42 };
Object.keys(obj)
// ["foo", "baz"]

 

Object.values()

遍歷屬性的鍵值,返回一個數組,成員參數是對象自身的(不含繼承)所有可遍歷(enumerable)屬性的鍵值

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

object.values()會過濾屬性名爲Symbol值的屬性,如果參數是一個字符串,會返回各個字符組成的一個數組

字符串會先轉化成一個類似數組的對象.字符串的每個字符,就是該對象的一個屬性.因此Object.values()

返回每個屬性的鍵值,就是各個字符組成的一個數組

如果參數不是對象,會先將其轉化成對象,由於數值和布爾值的包裝對象,都不會爲實例添加非繼承的屬性,會返回空數組

Object.values(42) // []
Object.values(true) // []

Object.entries() 

遍歷屬性的鍵值對數組,返回一個數組,成員是參數對象自身的(不可繼承)所有可遍歷的屬性的鍵值對數組

忽略Symbol值的屬性

Object.entries方法的一個用處是,將對象轉爲真正的Map結構

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

對象的擴展運算符(...)

( 具體內容移步到es6-----數組的擴展中,鏈接::  https://mp.csdn.net/console/editor/html/104451458)

 

Object.getOwnPropertyDescriptors()

返回某個對象屬性的描述對象

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章