JS-對象

1、概述

JS是一種面向對象的語言。除了基本數據類型number, string, boolean(true, false), null, undefined,其餘的都是對象。對象就是一個"name-value"對集合。javascript

2、操做對象

2.1 建立對象

JS有三種建立對象的方式:字面量,Object.create,new構造方式。java

2.1.1 Object.create(null | object)

嚴格來講調用Object.create方法是建立JS對象的惟一方式(其餘兩種方式內部實現都是基於該方法的)。該方法功能是建立一個對象,而且該對象的原型指向create的參數對象。
參數:必須是null或者對象,不然報錯。null表示建立一個沒有原型的空對象。segmentfault

var p = { a: 1}; // 對象字面量
var c1 = Object.create(p); // 對象c1的原型指向p
var c2 = Object.create(null);// 對象c2沒有原型

clipboard.png

2.1.2 對象字面量

對象字面量是一種建立對象的便捷方式,見上例。其中對象p的建立方式就是對象字面量。JS解釋器會對它進行處理的,等價於:數組

var p = Object.create(Object.prototype);
p.a = 1;

因此說對象字面量內部也是經過Object.create方式建立對象的,而且全部對象字面量方式建立的對象的原型都執行Object.prototype(如上圖)。app

思考:JS解釋器如何區分語句塊花括號{}和空對象花括號{}的?
先看看這兩條語句執行的結果?函數

{} + [] // 0
[] + {} // "[object Object]"
  1. {}做爲右值(賦值表達式右側),實參,在運算符的右側,被括號()包裹則做爲對象,其餘則視爲語句塊:
    下面輸出都是:"[object Object]"this

    console.log({} + []) // 做爲實參了
    
    ({}) + [] // 被括號包裹
    
    var a = {} + [] //做爲右值
    console.log(a)
  2. 咱們知道當ES6箭頭函數的函數體只有一條語句時能夠省略語句塊花括號,可是若是箭頭函數返回的是一個對象該如何書寫呢?spa

    var func1 = () => {age: 12} // 本意是想返回對象{age:12},顯然這樣寫就不對了,花括號會被做爲語句塊解析
    var func2 = () => ({age: 12}) // 能夠用括號包裹下
    var func3 = () => { return {age: 12}} // 或顯示的寫全

2.1.3 new構造方式

JS的做者爲了討好類語言的開發者,引入了第三者建立對象方式,即new構造方式。這使得JS對象的建立有點像類語言的對象建立。prototype

1) 格式
new關鍵字 + 空格 + 函數名字 + [(參數)]

其中參數是可選的,當沒有參數傳遞時,能夠省略括號。如:code

function Func(){}
var c1 = new Func();
var c2 = new Func; // 若是沒有參數傳遞,能夠省略括號。
function Func(name){
  this.name = name;
}
Func.prototype.say = function(){
};
var c = new Func('q');

clipboard.png

2) 內部原理

這種方式的內部也是經過Object.create方式構建的。new方式建立對象大體分爲三步:
Step1:建立一個對象A,而且對象A的原型指向構造函數的prototype屬性
Step2:以對象A綁定到構造函數上調用構造函數
Step3:若是構造函數返回值不是個非null的對象,則返回構造函數的返回值做爲new表達式的值,不然以對象A做爲new表達式的值。

function Func(name){
  this.name = name;
}
Func.prototype.say = function(){
};
function create(){ // 模擬new操做符
  var func = arguments[0];
  var args = Array.prototype.slice.call(arguments, 1);
  var other = Object.create(func.prototype); // Step 1
  var result = func.apply(other, args); // Step 2
  return typeof result === 'object' && result ? result: other; // Step3 注意返回值
}
var c = create(Func, 'q');

2.2 訪問對象屬性

訪問方式也就是get/set/delete。在get訪問中會涉及原型鏈,set/delete訪問不會。

var Obj = {
  name: 'john'
};
// Get操做
var n = Obj.name; // 等價var n = Obj["name"];
// Set操做
Obj.age = 12;

2.2.1 Get操做流程:

clipboard.png

2.2.2 Set操做流程:

clipboard.png

2.2.3 delete操做

能夠經過delete操做符刪除對象的屬性,只能刪除對象自己的屬性。

var p = {
  age: 26
}
var obj = Object.create(p);
obj.name = 'john';
console.log(obj.name); // john
console.log(obj.age); // 26
delete obj.name; // 刪除屬性
delete obj.age; // 刪除屬性
console.log(obj.name); // undefined
console.log(obj.age); // undefined

clipboard.png

2.3 引用對象

JS中對象是引用類型的。對象在做爲值時,是做爲引用傳遞的。

var a={}, b={}; // a,b分別指向不一樣的對象
var c = d = {}; // c,d指向同一個對象

3、反射

肯定對象的類型有時頗有必要。

3.1 typeof 操做符

經過typeof操做符能夠獲取值的類型:

console.log(typeof 1); // number
console.log(typeof ''); // string
console.log(typeof null); // object
console.log(typeof undefined); // undefined
console.log(typeof true); // boolean
console.log(typeof {}); // object
console.log(typeof []); // object
console.log(typeof function(){}); // function

可是發現這種方式中null, 數組也都是返回「object」。緣由是JS中沒有原生數組類型,數組是經過對象模擬的,因此數組也是對象。可是如何區分數組和對象呢???

3.2 Object.prototype.toString

typeof是有缺陷的,在實際應用中常經過Object.prototype.toString方法肯定對象類型的。

console.log(Object.prototype.toString.call(1)); // [object Number]
console.log(Object.prototype.toString.call('')); // [object String]
console.log(Object.prototype.toString.call(null)); // [object Null]
console.log(Object.prototype.toString.call(undefined)); // [object Undefined]
console.log(Object.prototype.toString.call(true)); // [object Boolean]
console.log(Object.prototype.toString.call( {})); // [object Object]
console.log(Object.prototype.toString.call([])); // [object Array]
console.log(Object.prototype.toString.call(function(){})); // [object Function]

看例子中輸出結果中發現不一樣之處了吧。假如判斷對象是否爲數組:

var isArray = function(val){
  return Object.prototype.toString.call(val) === '[object Array]';
}

目前的不少庫zeptojs,underscorejs中都是這樣實現的。

相關文章
相關標籤/搜索