成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

整理Object的一些方法

Meils / 2188人閱讀

摘要:父類的原型方法子類調(diào)用構(gòu)造函數(shù)子類繼承父類前面說(shuō)到的,實(shí)際上是將第一個(gè)參數(shù)無(wú)論是原型對(duì)象還是普通對(duì)象的屬性添加到新創(chuàng)建對(duì)象的原型中,這也就意味著,通過(guò)中定義的屬性和方法是無(wú)法通過(guò)方法添加到新創(chuàng)建對(duì)象中的。

ES5 和 ES6 中 Object 添加了很多新的方法,現(xiàn)在很多開源代碼中有用到了這些,今天來(lái)整理一番。

Object.assign()

這是ES6新添加的方法,Object.assign()用來(lái)復(fù)制源對(duì)象的所有可枚舉屬性復(fù)制到目標(biāo)對(duì)象中,方法返回目標(biāo)對(duì)象。語(yǔ)法如下:

Object.assign(target, ...source);

source對(duì)象可以有很多個(gè),比如:

let target = {name: "target"};
let source1 = {age: 23};
let source2 = {email: "[email protected]"};
// ...
// let sourceN ={.....};
traget = Object.assign(target, source1, source2);

如果源對(duì)象和目標(biāo)對(duì)象的屬性的key相同,目標(biāo)對(duì)象的屬性將會(huì)被源對(duì)象中的屬性覆蓋。對(duì)于多個(gè)源對(duì)象來(lái)說(shuō),如果有相同的key,右邊的屬性將覆蓋左邊的屬性。這個(gè)方法只能將源對(duì)象的可枚舉對(duì)象和自己的屬性復(fù)制給目標(biāo)對(duì)象。

什么是可枚舉對(duì)象()?
可枚舉屬性是指那些內(nèi)部 “可枚舉” 標(biāo)志設(shè)置為true的屬性,對(duì)于通過(guò)直接的賦值和屬性初始化的屬性,該標(biāo)識(shí)值默認(rèn)為即為true,對(duì)于通過(guò)Object.defineProperty等定義的屬性,該標(biāo)識(shí)值默認(rèn)為false??擅杜e的屬性可以通過(guò) for...in 循環(huán)進(jìn)行遍歷(除非該屬性名是一個(gè) Symbol)。

對(duì)于源對(duì)象,Object.assign使用[[Get]],而在目標(biāo)對(duì)象上使用[[Set]],也就是說(shuō),使用這個(gè)方法會(huì)源對(duì)象的getter和目標(biāo)對(duì)象的setters。所以其本質(zhì)就是定義或者復(fù)制一個(gè)新的屬性。如果等待合并的源對(duì)象包含了getters,那就不太適合用來(lái)將源對(duì)象合并到原型中。假如復(fù)制的屬性到原型里,包括它們的可枚舉屬性,那么應(yīng)該使用 Object.getOwnPropertyDescriptor() 和 Object.defineProperty() 。String 和 Symbol 屬性都是會(huì)被復(fù)制的。

如果遇到了一個(gè)錯(cuò)誤,比如目標(biāo)對(duì)象的某個(gè)屬性是不可修改的,會(huì)拋出一個(gè)TypeError的錯(cuò)誤嗎,目標(biāo)對(duì)象保持不變

var foo = {}
Object.defineProperty(foo, "name", {
  writable: false,
  value: "zhanglun"
});
Object.assign(foo, {name: "zhangxiaolun"}); // TypeError: Cannot assign to read only property "1" of object "#"

如果源對(duì)象是null或者undefined,Object.assign()不會(huì)拋出錯(cuò)誤:

var foo = {name: "zhanglun"};
Object.assign(foo, null, undefined);
console.log(foo); // foo: {name: "zhanglun"}
Object.create()

通過(guò)指定的原型對(duì)象和屬性,創(chuàng)建一個(gè)新的對(duì)象。語(yǔ)法如下:

Object.create(proto, [,. propertiesObject]);

第一個(gè)參數(shù)是一個(gè)對(duì)象,可以是一個(gè)普通的對(duì)象,比如:{name: "zhanglun"},也可以是一個(gè)新創(chuàng)建的對(duì)象的原型(prototype),比如:new Array().prototype。無(wú)論是那種,都是 JavaScript 中的 Object,其屬性都被添加到返回的對(duì)象原型中;第二個(gè)參數(shù)是可選的,但是不能是undefined,該對(duì)象自身?yè)碛械目擅杜e屬性會(huì)被添加到新創(chuàng)建的對(duì)象上,其原型鏈上的屬性是無(wú)效的。如果第一個(gè)參數(shù)不是null或者一個(gè)對(duì)象值,將會(huì)拋出TypeError異常。

Object.create()最直接的作用是基于一個(gè)對(duì)象創(chuàng)建新的對(duì)象,更多時(shí)候用在了原型鏈繼承上,先來(lái)看看 JavaScript
中創(chuàng)建對(duì)象的幾種方法:

對(duì)象字面量

var o = {a: 1};

// o這個(gè)對(duì)象繼承了Object.prototype上面的所有屬性
// 所以可以這樣使用 o.hasOwnProperty("a").
// hasOwnProperty 是Object.prototype的自身屬性。
// Object.prototype的原型為null。
// 原型鏈如下:
// o ---> Object.prototype ---> null

var a = ["yo", "whadup", "?"];

// 數(shù)組都繼承于Array.prototype 
// (indexOf, forEach等方法都是從它繼承而來(lái)).
// 原型鏈如下:
// a ---> Array.prototype ---> Object.prototype ---> null

function f(){
  return 2;
}

// 函數(shù)都繼承于Function.prototype
// (call, bind等方法都是從它繼承而來(lái)):
// f ---> Function.prototype ---> Object.prototype ---> null

構(gòu)造函數(shù)

在 JavaScript 中,構(gòu)造器其實(shí)就是一個(gè)普通的函數(shù)。當(dāng)使用 new 操作符 來(lái)作用這個(gè)函數(shù)時(shí),它就可以被稱為構(gòu)造方法(構(gòu)造函數(shù))。如果沒(méi)有 new 關(guān)鍵字而是直接調(diào)用的話,相當(dāng)于是在當(dāng)前作用域上調(diào)用,此時(shí)函數(shù)中如果有 this 的話,this 指向的是當(dāng)前作用域。

function Graph() {
  this.vertexes = [];
  this.edges = [];
}

Graph.prototype = {
  addVertex: function(v){
    this.vertexes.push(v);
  }
};

var g = new Graph();
// g是生成的對(duì)象,他的自身屬性有"vertices"和"edges".
// 在g被實(shí)例化時(shí),g.[[Prototype]]指向了Graph.prototype.
Graph();
console.log(window.vertexes); // 在全局作用域中調(diào)用,意外地增加了全局變量

使用 Object.create()

var a = {a: 1}; 
// a ---> Object.prototype ---> null

var b = Object.create(a);
// b ---> a ---> Object.prototype ---> null
console.log(b.a); // 1 (繼承而來(lái))

var c = Object.create(b);
// c ---> b ---> a ---> Object.prototype ---> null

var d = Object.create(null);
// d ---> null
console.log(d.hasOwnProperty); // undefined, 因?yàn)閐沒(méi)有繼承Object.prototype

ES6 中的 Class 關(guān)鍵字

ES6 引入了一套新的關(guān)鍵字用來(lái)實(shí)現(xiàn) class。這是一個(gè)語(yǔ)法糖,其本質(zhì)還是基于原型的。這些新的關(guān)鍵字包括 class, constructor, static, extends, 和 super。關(guān)于 Class的使用,回頭再開一篇文章深入學(xué)習(xí)。

"use strict";

class Polygon {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}

class Square extends Polygon {
  constructor(sideLength) {
    super(sideLength, sideLength);
  }
  get area() {
    return this.height * this.width;
  }
  set sideLength(newLength) {
    this.height = newLength;
    this.width = newLength;
  }
}

var square = new Square(2);
使用 Object.create() 實(shí)現(xiàn)繼承

下面是一個(gè)使用 Object.create()實(shí)現(xiàn)類的繼承的例子。

function Shape() {
  this.x = 0;
  this.y = 0;
}

// 父類的原型方法
Shape.prototype.move = function(x, y) {
  this.x += x;
  this.y += y;
  console.info("Shape moved.");
};

// 子類
function Rectangle() {
  Shape.call(this); // 調(diào)用構(gòu)造函數(shù)
}

// 子類繼承父類
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 VS new

前面說(shuō)到的,Object.create實(shí)際上是將第一個(gè)參數(shù)(無(wú)論是原型對(duì)象還是普通對(duì)象)的屬性添加到新創(chuàng)建對(duì)象的原型中,這也就意味著,通過(guò)new Function()中定義的屬性和方法是無(wú)法通過(guò) create()方法添加到新創(chuàng)建對(duì)象中的。

Object.create創(chuàng)建一個(gè)新的對(duì)象,這個(gè)對(duì)象“繼承”了第一個(gè)參數(shù)。構(gòu)造函數(shù)新創(chuàng)建的對(duì)象“繼承”構(gòu)造函數(shù)的prototype。

let o = new SomeConstructor();  // o 直接繼承自`SomeConstructor.prototype`。

兩者的最明顯的不同之處在于:如果 Object.create()的第一個(gè)參數(shù)是null,新創(chuàng)建的對(duì)象不會(huì)“繼承”自任何地方,沒(méi)有原型,也沒(méi)有往上追溯的原型;在使用構(gòu)造函數(shù)時(shí),如果將其原型設(shè)置為 null,SomeConstructor.prototype = null;,新創(chuàng)建的對(duì)象將會(huì)“繼承”自 Object 的 prototype。

Object.freeze()

字面意思就是將一個(gè) object“凍住”:不能添加新的屬性;不能刪除現(xiàn)有的屬性;不能修改現(xiàn)有屬性,包括屬性的enumerability, configurability和 writability。這個(gè)方法返回一個(gè)不可修改的對(duì)象,使用語(yǔ)法:

Object.freeze(obj)

任何嘗試修改該對(duì)象的操作都會(huì)失敗,可能是靜默失敗,也可能會(huì)拋出異常。在嚴(yán)格模式中會(huì)拋出異常(本地測(cè)試下來(lái)嚴(yán)格模式也不會(huì)報(bào)錯(cuò))。數(shù)據(jù)屬性的值不可更改,訪問(wèn)器屬性(有g(shù)etter和setter)也同樣,但由于是函數(shù)調(diào)用,給人一種修改了這個(gè)屬性的錯(cuò)覺(jué)。如果一個(gè)屬性的值是個(gè)對(duì)象,則這個(gè)對(duì)象中的屬性是可以修改的,除非它也是個(gè)凍結(jié)對(duì)象。

let foo = {
  name: "zhanglun",
  age: 23,
}

console.log(foo.name); // "zhanglun"
console.log(foo.age); // 23

foo.name = "zhanglun1410";
foo.age = 24;

console.log(foo.name); // "zhanglun1410"
console.log(foo.age); // 24

Object.freeze(foo);

foo.name = "zzzz"; // 靜默失敗
console.log(foo.name); // "zhanglun1410"

"use strict";
foo.name = "zzzz"; // TypeError 或者 靜默失敗
console.log(foo.name); // "zhanglun1410"
Object.freeze VS const

被凍結(jié)的對(duì)象是不可改變的。但是它不一定是常量。對(duì)常量而言,它的所有引用,無(wú)論是直接的還是間接的都是引用的不可改變的對(duì)象。string,number,和 boolean 總是不可變的(當(dāng)你把一個(gè)變量從字符串 A 修改到字符串 B時(shí),A 和 B 都是不可變的,A 還是 A,B 也還是 B,只不過(guò)變量的之前指向的是 A,修改之后指向了 B)。通常來(lái)說(shuō),一般不會(huì)創(chuàng)建一個(gè)對(duì)象常量,也不存在freezeAll()這樣的方法。

const 用于聲明常量,將變量綁定到一個(gè)不可修改的對(duì)象,常量最終指向的是一個(gè)不可修改的對(duì)象,比如一個(gè)被凍結(jié)的對(duì)象,而 Object.freeze 作用在對(duì)象的值上,將一個(gè)對(duì)象變成不可修改的對(duì)象。

深度凍結(jié)對(duì)象

前面提到的,Object.freeze作用在對(duì)象的屬性上,使對(duì)象的屬性不可修改。而如果屬性值也是一個(gè)對(duì)象的話,依然能夠修改,除非這個(gè)對(duì)象也被凍結(jié)了。因此,可以把 Object.freeze 理解成是“淺凍結(jié)”??梢跃帉戭~外的代碼來(lái)實(shí)現(xiàn)“深凍結(jié)”:

obj1 = {
  internal: {}
};

Object.freeze(obj1);
obj1.internal.a = "aValue";

obj1.internal.a // "aValue"

// 深度凍結(jié)
function deepFreeze(obj) {

  // 獲取到對(duì)象的屬性的名字
  var propNames = Object.getOwnPropertyNames(obj);

  // 先凍結(jié)內(nèi)部的對(duì)象
  propNames.forEach(function(name) {
    var prop = obj[name];

    // Freeze prop if it is an object
    if (typeof prop == "object" && prop !== null)
      deepFreeze(prop);
  });

  // 凍結(jié) obj
  return Object.freeze(obj);
}

obj2 = {
  internal: {}
};

deepFreeze(obj2);
obj2.internal.a = "anotherValue";
obj2.internal.a; // undefined
Object.freeze 的注意事項(xiàng)

在 ES5 中,如果參數(shù)不是一個(gè)對(duì)象,是一個(gè)原始數(shù)據(jù)類型,會(huì)拋出 TypeError。在 ES6 中,不是對(duì)象的參數(shù)的會(huì)被當(dāng)做是一個(gè)已經(jīng)被凍結(jié)的普通對(duì)象,只是返回這個(gè)參數(shù)。

Object.defineProperty()

Object.defineProperty是ES5新增的一個(gè)方法,可以給對(duì)象的屬性增加更多的控制。語(yǔ)法如下:

Object.defineProperty(obj, prop, descriptor)

前面兩個(gè)參數(shù)很簡(jiǎn)單,修改的對(duì)象和修改或者新增的屬性,著重介紹一下第三個(gè)參數(shù):屬性描述符。

ES5 中定義了一個(gè)名叫“屬性描述符”的對(duì)象,用于描述了的各種特征,它本身是一個(gè) Object。屬性描述符對(duì)象有4個(gè)屬性:

configurable:可配置性,控制著其描述的屬性的修改,表示能否修改屬性的特性,能否把屬性修改為訪問(wèn)器屬性,或者能否通過(guò)delete刪除屬性從而重新定義屬性。默認(rèn)值為true。

enumerable:可枚舉性,表示能否通過(guò)for-in遍歷得到屬性。默認(rèn)值為true。

writable:可寫性,表示能否修改屬性的值。默認(rèn)值為true。

value:數(shù)據(jù)屬性,表示屬性的值。默認(rèn)值為undefined。

和兩個(gè)存取器屬性,分別是get和set,可以代替value和writable。

get:在讀取屬性時(shí)調(diào)用的函數(shù)。只指定get則表示屬性為只讀屬性。默認(rèn)值為undefined。

set:在寫入屬性時(shí)調(diào)用的函數(shù)。只指定set則表示屬性為只寫屬性。默認(rèn)值為undefined。

屬性描述符只能在Object.definePropertyObject.defineProperties中使用。

var o = {}; // Creates a new object

// Example of an object property added with defineProperty with a data property descriptor
// 添加屬性 a,值為37,并設(shè)置屬性描述符
Object.defineProperty(o, "a", {
  value: 37,
  writable: true,
  enumerable: true,
  configurable: true
});


var bValue = 38;
Object.defineProperty(o, "b", {
  get: function() { return bValue; },
  set: function(newValue) { bValue = newValue; },
  enumerable: true,
  configurable: true
});
o.b; // 38
// o 對(duì)象中存在屬性 b,他的值為38;
// 只要 o.b沒(méi)有重新定義,它的值永遠(yuǎn)都是38

// 訪問(wèn)器不能和 value或者 writable混在一起用
Object.defineProperty(o, "conflict", {
  value: 0x9f91102,
  get: function() { return 0xdeadbeef; }
});
// 拋出一個(gè)錯(cuò)誤 Uncaught TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, #
Object.defineProperties()

相比 Object.defineProperty, Object.defineProperties可以說(shuō)是前者的升級(jí)版,可以一次同時(shí)定義多個(gè)屬性,語(yǔ)法略有不同:

let obj = {};
Object.defineProperties(obj, {
  "property1": {
    value: true,
    writable: true
  },
  "property2": {
    value: "Hello",
    writable: false
  },
  "property3": {
    get: function() {
      return "Hello, Object.defineProperties";
    },
    set:function() {
      this.property2 = "xxxxxx";
    }
  }
  // etc. etc.
});

參考資料:

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze

http://stackoverflow.com/a/17952160

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/81365.html

相關(guān)文章

  • JS整理知識(shí)點(diǎn)5.10

    摘要:將這個(gè)空對(duì)象的原型,指向構(gòu)造函數(shù)的屬性。構(gòu)造函數(shù)內(nèi)部,指的是一個(gè)新生成的空對(duì)象,所有針對(duì)的操作,都會(huì)發(fā)生在這個(gè)空對(duì)象上。構(gòu)造函數(shù)之所以叫構(gòu)造函數(shù),就是說(shuō)這個(gè)函數(shù)的目的,就是操作一個(gè)空對(duì)象即對(duì)象,將其構(gòu)造為需要的樣子。 toString() 的應(yīng)用:判斷數(shù)據(jù)類型為了得到類型字符串,最好直接使用Object.prototype.toString方法。通過(guò)函數(shù)的call方法,可以在任意值上調(diào)...

    Acceml 評(píng)論0 收藏0
  • JavaScript學(xué)習(xí)筆記整理:對(duì)象篇

    摘要:函數(shù)式對(duì)象的一個(gè)子類型,中的函數(shù)是一等公民內(nèi)置對(duì)象中還有一些對(duì)象子類型,通常被稱為內(nèi)置對(duì)象。內(nèi)容對(duì)象的內(nèi)容是由一些存儲(chǔ)在特定命名位置的任意類型的值組成的,我們稱之為屬性。 語(yǔ)法 對(duì)象兩種定義形式 聲明(文字)形式 構(gòu)造形式 //聲明(文字)形式 var myObj = { key: value // ... } //構(gòu)造形式 var myObj = new Ob...

    testbird 評(píng)論0 收藏0
  • 反射(筆記整理)

    摘要:調(diào)用構(gòu)造函數(shù)對(duì)該對(duì)象進(jìn)行初始化。,并將該字節(jié)碼文件封裝成了對(duì)象。清單,獲取字節(jié)碼文件中的字段。 1、什么是反射技術(shù)?動(dòng)態(tài)獲取指定類以及類中的內(nèi)容(成員),并運(yùn)行其內(nèi)容。應(yīng)用程序已經(jīng)運(yùn)行,無(wú)法在其中進(jìn)行new對(duì)象的建立,就無(wú)法使用對(duì)象。這時(shí)可以根據(jù)配置文件的類全名去找對(duì)應(yīng)的字節(jié)碼文件,并加載進(jìn)內(nèi)存,并創(chuàng)建該類對(duì)象實(shí)例。這就需要使用反射技術(shù)完成 2、獲取class對(duì)象的三種方式獲取Clas...

    QiuyueZhong 評(píng)論0 收藏0
  • JavaScript易錯(cuò)知識(shí)點(diǎn)整理

    摘要:知識(shí)點(diǎn)變量作用域上方的函數(shù)作用域中聲明并賦值了,且在之上,所以遵循就近原則輸出等于。上方的函數(shù)作用域中被重新賦值,未被重新聲明,且位于之下,所以輸出全局作用域中的。若執(zhí)行則會(huì)輸出。上方利用方法進(jìn)行對(duì)象的深拷貝可以避免源對(duì)象被篡改的可能。 前言 本文是我學(xué)習(xí)JavaScript過(guò)程中收集與整理的一些易錯(cuò)知識(shí)點(diǎn),將分別從變量作用域,類型比較,this指向,函數(shù)參數(shù),閉包問(wèn)題及對(duì)象拷貝與賦值...

    2shou 評(píng)論0 收藏0
  • JavaScript易錯(cuò)知識(shí)點(diǎn)整理

    摘要:知識(shí)點(diǎn)變量作用域上方的函數(shù)作用域中聲明并賦值了,且在之上,所以遵循就近原則輸出等于。上方的函數(shù)作用域中被重新賦值,未被重新聲明,且位于之下,所以輸出全局作用域中的。上方利用方法進(jìn)行對(duì)象的深拷貝可以避免源對(duì)象被篡改的可能。 前言 本文是我學(xué)習(xí)JavaScript過(guò)程中收集與整理的一些易錯(cuò)知識(shí)點(diǎn),將分別從變量作用域,類型比較,this指向,函數(shù)參數(shù),閉包問(wèn)題及對(duì)象拷貝與賦值這6個(gè)方面進(jìn)行由...

    vincent_xyb 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<