JS Object對象的方法總結( ES5 與 ES6 )

ES5中的方法

Object 對象的靜態方法

所謂「靜態方法」,是指部署在Object對象自身的方法   ---(此句話摘自 阮一峯博客)數組

Object.keys()方法與Object.getOwnPropertyNames方法很類似,通常用來遍歷對象的(屬性名,索引),並返回一個數組,該數組成員都是對象自身的(不是繼承的),區別在於Object.keys方法只返回可枚舉的屬性,Object.getOwnPropertyNames方法還能返回不可枚舉的屬性名函數

1.Object.keysthis

// 定義一個 Array 對象
let arr = ["a", "b", "c"];

// 定義一個 Object 對象
let obj = { foo: "bar", baz: 42 };

// 定義一個  類數組 對象 
let ArrayLike = { 0 : "a", 1 : "b", 2 : "c"};

// 類數組 對象, 隨機 key 排序 
let anObj = { 100: 'a', 2: 'b', 7: 'c' }; 

/* getFoo 是個不可枚舉的屬性 */ 
var my_obj = Object.create({}, {
     getFoo : { value : function () { return this.foo } }
 }
);
my_obj.foo = 1;

// 打印結果
console.log(Object.keys(arr));       // ['0', '1', '2']
console.log(Object.keys(obj));       // ["foo","baz"]
console.log(Object.keys(ArrayLike));     // ['0', '1', '2']
console.log(Object.keys(anObj));   // ['2', '7', '100']
console.log(Object.keys(my_obj)); // ['foo']

返回數組中的排序與for..in是一致的,區別在於for..in循環還能夠枚舉原型鏈上的屬性spa

2.Object.getOwnPropertyNamesprototype

// 定義一個數組
var arr = ["a", "b", "c"];

// 定義一個 類數組對象
var obj = { 0: "a", 1: "b", 2: "c"};

//定義一個 不可枚舉屬性
var my_obj = Object.create({}, {
  getFoo: {
    value: function() { return this.foo; },
    enumerable: false
  }
});
my_obj.foo = 1;

// 打印結果
console.log(Object.getOwnPropertyNames(arr).sort()); // ["0", "1", "2", "length"]
console.log(Object.getOwnPropertyNames(obj).sort()); // ["0", "1", "2"]
console.log(Object.getOwnPropertyNames(my_obj).sort()); // ["foo", "getFoo"]

3.對象屬性相關的方法翻譯

// 看此方法以前,我以爲應該先了解一下,對象的屬性分爲哪兩種,插句題外話,O(∩_∩)O哈哈~

  對象裏目前存在的屬性描述符有兩種主要形式:數據描述符  和 存取描述符code

    數據描述符: 是一個具備值的屬性,該值多是可寫的,也可能不是可寫的。對象

    訪問器描述符: 是由getter-setter函數對描述的屬性。描述符必須是這兩種形式之一;不能同時是二者。blog

  數據描述符和存取描述符均具備如下可選鍵值:排序

    configurable: 當且僅當該屬性的 configurable 爲 true 時,該屬性描述符纔可以被改變,同時該屬性也能從對應的對象上被刪除。默認爲 false。

    enumerable: 當且僅當該屬性的enumerabletrue時,該屬性纔可以出如今對象的枚舉屬性中。默認爲 false。

    value: 該屬性對應的值。能夠是任何有效的 JavaScript 值(數值,對象,函數等)。默認爲 undefined。

    writable: 當且僅當該屬性的writabletrue時,value才能被賦值運算符改變。默認爲 false

    getter: 一個給屬性提供 getter 的方法,若是沒有 getter 則爲 undefined。該方法返回值被用做屬性值。默認爲 undefined。

    setter:  一個給屬性提供 setter 的方法,若是沒有 setter 則爲 undefined。該方法將接受惟一參數,並將該參數的新值分配給該屬性。默認爲 undefined。

     注意:若是一個描述符同時設置value,writable,get和set關鍵字,它將被認爲是一個數據描述符。若是一個描述符同時有value或writable和get或set關鍵字,將產生異常。

    記住,這些選項不必定是自身屬性,若是是繼承來的也要考慮。爲了確認保留這些默認值,你可能要在這以前凍結 Object.prototype,明確指定全部的選項,或者將 __proto__屬性指向null

  a).Object.getOwnPropertyDescriptor( obj, prop) 返回一個指定對象上的自有屬性對應的屬性描述 (自由屬性指,直接賦值的屬性,不須要從原型上查找的屬性)

   參數:

    obj 須要查找的目標對象

    prop 目標對象內的屬性名稱

let o = { get foo() { return 17; } };
let d = Object.getOwnPropertyDescriptor(o, "foo");

let o1 = { bar: 42 };
let d1 = Object.getOwnPropertyDescriptor(o1, "bar");

let o2 = {};
Object.defineProperty(o2, "baz", {
    value: 8675309,
    writable: false,
    enumerable: false
});
let d2 = Object.getOwnPropertyDescriptor(o2, "baz");
console.log(d)// {configurable: true, enumerable: true, get: [Function: get foo],set: undefined}
console.log(d1)//{configurable: true, enumerable: true, value: 42, writable: true}
console.log(d2)// {value: 8675309, writable: false, enumerable: false, configurable: false}

注意事項:ES5第一個參數不是對象,就會產生TypeError, ES2015第一個參數不是對象的話,就會被強制轉換成對象

  b).Object.defineProperty( obj, prop, decriptor)  直接在一個對象上定義一個新屬性,或修改一個對象的現有屬性,並返回這個對象,默認狀況下使用此方法添加的屬性值是不能被修改的

  參數:

    obj 要在其上定義屬性的對象

    prop 要定義或修改的屬性名稱

    decriptor 將被定義或修改的屬性描述符

var o = {}; // 建立一個新對象

// 在對象中添加一個屬性與數據描述符的示例
Object.defineProperty(o, "a", {
    value : 37,
    writable : true,
    enumerable : true,
    configurable : true
});
// 對象o擁有了屬性a,值爲37

// 在對象中添加一個屬性與存取描述符的示例
var bValue;
Object.defineProperty(o, "b", {
    get : function(){
        return bValue;
    },
    set : function(newValue){
        bValue = newValue;
    },
    enumerable : true,
    configurable : true
});
o.b = 38;
// 對象o擁有了屬性b,值爲38

// o.b的值如今老是與bValue相同,除非從新定義o.b

// 數據描述符和存取描述符不能混合使用
Object.defineProperty(o, "conflict", {
    value: 0x9f91102,
    get: function() {
        return 0xdeadbeef;
    }
});
// TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute(無效的屬性描述符,不能同時指定訪問器和值或可寫屬性)

  c).Object.defineProperties()

  d).Object.getOwnPropertyNames()

4.控制對象狀態的方法

  a).Object.preventExtensions() 防止對象擴展

  b).Object.isExtensible() 判斷對象是否可擴展

  c).Object.seal() 禁止對象配置

  d).Object.isSealed() 判斷一個對象是否可配置

  e).Object.freeze() 凍結一個對象

  f).Object.isFrozen() 判斷一個對象是否被凍結

5.原型鏈相關方法

  a).Object.creat() 能夠指定原型對象和屬性,返回一個新的對象

  b).Object.getPrototypeOf() 獲取對的的Prototype對象

Object對象的實例方法

除了Object對象自己的方法,還有很多方法是部署在Object.prototype對象上的,全部Object的實例對象都繼承了這些方法。Object實例對象的方法,主要有如下六個。(此句摘自 --阮一峯 博客)

  a). valueOf()返回當前對象對應的值

  b). toString()返回當前對象對應的字符串形式,用來判斷一個值的類型

  c). toLocaleString()返回當前對象對應的本地字符串形式

  d). hasOwnProperty()判斷某個屬性是否爲當前對象自身的屬性,仍是繼承自原型對象的屬性

  e). isPrototypeOf()判斷當前對象是否爲另外一個對象的原型

  f). propertyIsEnumerable()判斷某個屬性是否可枚舉

 ES6新增方法

(摘自 阮一峯ECMAScript 6 入門 )

1.屬性的簡潔寫法

  ES6 容許在對象之中,直接寫變量。這時,屬性名爲變量名, 屬性值爲變量的值。

  屬性簡寫

function f(x, y) {
  return {x, y};
}
// 等同於
function f(x, y) {
  return {x: x, y: y};
}
f(1, 2) // Object {x: 1, y: 2}

  方法名簡寫

const o = {
  method() {
    return "Hello!";
  }
};
// 等同於
const o = {
  method: function() {
    return "Hello!";
  }
};

  屬性簡寫與方法名簡寫,例:

let birth = '2000/01/01';
const Person = {
  name: '張三',
  //等同於birth: birth
  birth,
  // 等同於hello: function ()...
  hello() { console.log('個人名字是', this.name); }
};

  CommonJS 模塊輸出一組變量,就很是合適使用簡潔寫法

let ms = {};
function getItem (key) {
  return key in ms ? ms[key] : null;
}
function setItem (key, value) {
  ms[key] = value;
}
module.exports = { getItem, setItem };
// 等同於
module.exports = {
  getItem: getItem,
  setItem: setItem
};

  屬性的賦值器(setter)和取值器(getter),事實上也是採用這種寫法

const cart = {
  _wheels: 4,
  get wheels () {
    return this._wheels;
  },
  set wheels (value) {
    if (value < this._wheels) {
      throw new Error('數值過小了!');
    }
    this._wheels = value;
  }
}

2.屬性名錶達式

  方法一,是直接用標識符做爲屬性名

  方法二,是用表達式做爲屬性名,這時要將表達式放在方括號以內。

// 方法一
obj.foo = true;
// 方法二
obj['a' + 'bc'] = 123;

  表達式還能夠用作方法名

let obj = {
  ['h' + 'ello']() {
    return 'hi';
  }
};
obj.hello() // hi

  注意,屬性名錶達式與簡潔表示法,不能同時使用,會報錯。

// 報錯
const foo = 'bar';
const bar = 'abc';
const baz = { [foo] };

// 正確
const foo = 'bar';
const baz = { [foo]: 'abc'};

  注意,屬性名錶達式若是是一個對象,默認狀況下會自動將對象轉爲字符串[object Object],這一點要特別當心。

const keyA = {a: 1};
const keyB = {b: 2};

const myObject = {
  [keyA]: 'valueA',
  [keyB]: 'valueB'
};

myObject // Object {[object Object]: "valueB"}

  上面代碼中,[keyA][keyB]獲得的都是[object Object],因此[keyB]會把[keyA]覆蓋掉,而myObject最後只有一個[object Object]屬性。

3.方法的 name 屬性

  若是對象的方法使用了取值函數(getter)和存值函數(setter),則name屬性不是在該方法上面,而是該方法的屬性的描述對象的getset屬性上面,返回值是方法名前加上getset

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

  ES5 比較兩個值是否相等,只有兩個運算符:相等運算符(==)和嚴格相等運算符(===)。它們都有缺點,前者會自動轉換數據類型,後者的NaN不等於自身,以及+0等於-0。JavaScript 缺少一種運算,在全部環境中,只要兩個值是同樣的,它們就應該相等。

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

  ES5 能夠經過下面的代碼,部署Object.is

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
});

5.Object.assign( target, source, source1 ) 方法用於對象的合併,將源對象(source)的全部可枚舉屬性,複製到目標對象(target)。拷貝的屬性是有限制的,只拷貝源對象的自身屬性(不拷貝繼承屬性),也不拷貝不可枚舉的屬性(enumerable: false

  參數

    target 目標對象

    source 源對象

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

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

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

  注意,若是目標對象與源對象有同名屬性,或多個源對象有同名屬性,則後面的屬性會覆蓋前面的屬性。

let obj = {a: 1};
Object.assign(obj, undefined) === obj // true
Object.assign(obj, null) === obj /

  若是非對象參數出如今源對象的位置(即非首參數),那麼處理規則有所不一樣。首先,這些參數都會轉成對象,若是沒法轉成對象,就會跳過。這意味着,若是undefinednull不在首參數,就不會報錯。

注意:

  a). Object.assign方法實行的是淺拷貝,而不是深拷貝。也就是說,若是源對象某個屬性的值是對象,那麼目標對象拷貝獲得的是這個對象的引用。

const obj1 = {a: {b: 1}};
const obj2 = Object.assign({}, obj1);

obj1.a.b = 2;
console.log(obj2.a.b) //2
obj2.a.b = 3
console.log(obj1.a.b) //3

  上面代碼中,源對象obj1a屬性的值是一個對象,Object.assign拷貝獲得的是這個對象的引用。這個對象的任何變化,都會反映到目標對象上面。

   b).  數組的處理

Object.assign([1, 2, 3], [4, 5])// [4, 5, 3]

  上面代碼中,Object.assign把數組視爲屬性名爲 0、一、2 的對象,所以源數組的 0 號屬性4覆蓋了目標數組的 0 號屬性1

常見用途

  a). 爲對象添加屬性

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

  上面方法經過Object.assign方法,將x屬性和y屬性添加到Point類的對象實例。 

  b). 爲對象添加方法

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

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

  上面代碼使用了對象屬性的簡潔表示法,直接將兩個函數放在大括號中,再使用assign方法添加到SomeClass.prototype之中。

  c). 克隆對象

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

  上面代碼將原始對象拷貝到一個空對象,就獲得了原始對象的克隆。

  不過,採用這種方法克隆,只能克隆原始對象自身的值,不能克隆它繼承的值。若是想要保持繼承鏈,能夠採用下面的代碼。

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

  d). 合併多個對象,將多個對象合併到某個對象。

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

//若是但願合併後返回一個新對象,能夠改寫上面函數,對一個空對象合併。

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

  e). 爲屬性指定默認值

6.屬性的可枚舉和可遍歷

  可枚舉性

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

  a). Object.getOwnPropertyDescriptor方法能夠獲取該屬性的描述對象。

let obj = { foo: 123 };
Object.getOwnPropertyDescriptor(obj, 'foo')
//  { value: 123, writable: true, enumerable: true, configurable: true }

  目前,有四個操做會忽略enumerablefalse的屬性。

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

    Object.keys()返回對象自身的全部可枚舉的屬性的鍵名。

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

    Object.assign() 忽略enumerablefalse的屬性,只拷貝對象自身的可枚舉的屬性。

  ES6 規定,全部 Class 的原型的方法都是不可枚舉的。

  屬性的遍歷一共有5種:

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

    Object.keys返回一個數組,包括對象自身的(不含繼承的)全部可枚舉屬性(不含 Symbol 屬性)的鍵名。

    Object.getOwnPropertyNames返回一個數組,包含對象自身的全部屬性(不含 Symbol 屬性,可是包括不可枚舉屬性)的鍵名。

    Object.getOwnPropertySymbols返回一個數組,包含對象自身的全部 Symbol 屬性的鍵名。

    Reflect.ownKeys返回一個數組,包含對象自身的全部鍵名,無論鍵名是 Symbol 或字符串,也不論是否可枚舉。

 7.Object.getOwnPropertyDescriptors()

8.__proto__屬性,Object.setPrototypeOf(),Object.getPrototypeOf() 

9.super 關鍵字

10.Object.keys(),Object.values(),Object.entries()

 11.對象的擴展運算符

  a). 解構賦值

  b). 擴展運算符

 12.Null 傳導運算符

 

 

 

 

// 未完待續,內容慢慢添加,\(^o^)/~
相關文章
相關標籤/搜索