JavaScript對象

JavaScript對象

建立對象

  • 在JavaScript中,對象爲‘王’。
  • 對象只是一組有命名的值(也稱屬性)集合的容器。
// 建立對象
let cody = new Object();

// 爲cody對象的各類屬性賦值(使用點表示法)
cody.living = true;
cody.age = 33;
cody.gender = 'male';

console.log(cody); // 輸出object {living = true, age = 33, gender = 'male'}

Cody對象是一個值,經過建立對象將這個值表示JavaScript對象,給對象命名,而後將屬性賦值給對象。
  • 對象是屬性的容器,每一個屬性都有一個名稱和一個值。
  • JavaScript採用具備命名值屬性的容器(即對象)這一律念做爲在JavaScript中表達值的構建快。
  • 在JavaScript中,方法是包含Function()對象的屬性,其目的是對函數內部的對象進行操做。
// 建立對象
let cody = new Object();

// 爲cody對象的各類屬性賦值(使用點表示法)
cody.living = true;
cody.age = 33;
cody.gender = 'male';
cody.getGender = function() {return cody.gender;};

console.log(cody.getGenter()); // 輸出'male'

若是沒有方法,除了用於存儲靜態屬性意外,對象就沒有其餘太多用途。
  • 將構造函數視爲模板或者餅乾模具,來生成預約義對象。

由Object()構造函數建立的對象與經過string()構造函數建立的字符串對象沒有太大區別。javascript

let myObject = new Object();    // 生成一個Object對象
myObject['0'] = 'f';
myObject['1'] = 'o';
myObject['2'] = 'o';

console.log(myObject);  // 輸出Object{0='f',1='o',2='o'};

let myString = new String('foo');   // 生成一個string()對象

console.log(myString);  // 輸出 foo{0='f',1='o',2='o'}
  • javaScript是用對象來表示值的。
// 使用Object()構造函數建立codyA對象

let codyA = new Object();
codyA.living = true;
codyA.age = 33;
codyA.gender = 'male';
codyA.getGenter = function() {return codyA.gender;};

console.log(codyA); // 輸出Object{living= true,age=33,gender='male',...}

/*
*使用自定義Person()構造函數建立,而後使用'new'關鍵字進行實例化
*/

let Person = function (living, age, gender) {
    this.living = living;
    this.age = age;
    this.gender = gender;
    this.getGenter = function () {
        return this.gender;
    }
};

 // 輸出Object{living= true,age=33,gender='male',...}
let codyB = new Person(true, 33, 'male');
console.log(codyB);
  • JavaScript其實是一種預包裝若干原生對象構造函數的語言。這些構造函數生成一些表達特定類型值(如數字,字符串,函數,對象,數組)的複雜對象。
  • 也可經過Function()對象建立自定義的對象構造函數,不論是否是用於建立對象的模式,產生的最終結果一般是建立一個複雜的對象。

JavaScript構造函數構建並返回對象實例

  • 構造函數的做用是建立多個共享特定特性和行爲的對象。
  • 構造函數主要是一種用於生成對象的模型或者餅乾模具,這些對象具備默認屬性和屬性方法。
  • 若是使用'new'關鍵字調用某函數,JavaScript會給予該函數特殊待遇,將該函數的this設置爲正在構建的新對象,還默認返回新建立的對象(即this),而不是虛假值。該函數返回的新對象則被認爲是構建該對象的構造函數的實例。
// person是一個構造函數,可使用new關鍵字進行實例化
let Person = function(living, age, gender) {

    // 下面this表示即將建立的新對象(即,this = new Object();)
    this.living = living;
    this.age = age;
    this.gender = gender;
    this.getGender = function () {
        return this.gender;
    }
    // 一旦該Person函數使用new關鍵字調用,就返回this,而不是undefined。
};

// 實例化Person對象,命名爲Cody
let cody = new Person(true, 33, 'male');

// cody是一個對象,而且是Person()的一個實例
console.log(tyoeof cody);   // 輸出Objec
console.log(cody);  // 輸出cody內部的屬性和值
console.log(cody.constructor);  // 輸出Person()函數

自定義構造函數建立對象,與使用Array()構造函數建立Array()對象沒有什麼不一樣;java

// 實例化Array對象,命名爲myArray
let myArray = new Array();  // myArray是Array的一個實例

// myArray是一個對象,而且是Array()構造函數的一個實例

console.log(typeof myArray);    // 輸出Object

console.log(myArray);   // []

console.log(myArray.constructor);   // 輸出Array()
  • 在JavaScript中,大多數值(不包括原始值),都涉及到正在被建立的對象,或者是從構造函數實例化的對象。構造函數返回的對象被稱爲實例。

JavaScript原生/內置對象構造函數

  • JavaScript語言包含9哥原生(或內置)對象構造函數。
    • Number()
    • String()
    • Boolean()
    • Object()
    • Array()
    • Function()
    • Date()
    • RegExp()
    • Error()
  • JavaScript主要是由這9個對象(以及字符串,數字,布爾原始值)來建立的。
  • Math對象是一個靜態對象,而不是構造函數。咱們能夠直接使用它,而沒必要使用new關鍵字去調用。實際上Math只是一個由JavaScript設置的對象命名空間,用於存儲數學函數。
  • 原生對象也被稱爲‘全局對象’,在JavaScript中原生就是可使用的對象,它是做用域鏈中的最高層級。
  • Number()、String()、Boolean()構造函數不只能構建對象,並且能爲字符串、數字、布爾值提供原始值。若是直接調用這些構造函數,就會返回一個複雜對象。而若是隻是簡單的在代碼中表示一個數字、字符串、布爾值,那麼構造函數將返回一個原始值,而不是複雜的對象值。

用戶自定義/非原生對象構造函數

  • 自定義的構造函數,能夠生成多個自定義對象實例。
// person是一個構造函數,可使用new關鍵字進行實例化
let Person = function(living, age, gender) {

    // 下面this表示即將建立的新對象(即,this = new Object();)
    this.living = living;
    this.age = age;
    this.gender = gender;
    this.getGender = function () {
        return this.gender;
    }
    // 一旦該Person函數使用new關鍵字調用,就返回this,而不是undefined。
};

// 實例化Person對象,命名爲Cody
let cody = new Person(true, 33, 'male');
console.log(cody);  // 輸出object{living=true,age=33,gender='male',...};

let cody = new Person(true, 34, 'male');
console.log(cody);  // 輸出object{living=true,age=34,gender='male',...};
  • 建立自定義構造函數,只是在使用JavaScript自己在原生構造函數中所使用的相同的模式。
  • 建立將要與new操做符一塊兒使用的自定義構造函數時,最佳的作法是保持構造函數名稱的第一個字符大寫:Person(),而不是person()。

使用new操做符實例化構造函數

  • 構造函數從根本上來講時用於建立預配置對象的模具模版。
let myString = new String('foo');

console.log(myString);  // 輸出foo{0='f',1='o',2='o'}
  • JavaScript語言具備9種原生預約義的構造函數,能夠在任意一個構造函數上應用new操做符來實例化一個對象實例。
// 使用new關鍵字實例化每一個原生構造函數

let myNumber = new Number(33);
let myString = new String('male');
let myBoolean = new Boolean(false);
let myObject = new Object();
let myArray = new Array('foo','bar');
let myFunction = new Function('x','y','return x*y');
let myDate = new Date();
let myRegExp = new RegExp();
let myError = new Error();

// 輸出/驗證哪一個構造函數建立了該對象
console.log(myNumber.constructor);  // 輸出Number()
console.log(myString.constructor);  // 輸出String()
console.log(myBoolean.constructor);  // 輸出Boolean()
console.log(myArray.constructor);  // 輸出Array()
console.log(myFunction.constructor);  // 輸出Function()
console.log(myDate.constructor);  // 輸出Date()
console.log(myRegExp.constructor);  // 輸出RegExp()
console.log(myError.constructor);  // 輸出Error()
  • Math是一個靜態對象---其餘方法的容器,它不是使用new運算符的構造函數。

從構造函數建立字面量值

let myNumber = new Number(23); // 對象
let myNumberLiteral = 23;   // 原始數字值,而非對象

let myString = new String('male');  // 對象
let myStringLiteral = 'male'    // 原始字符值,而非對象

let myBoolean = new Boolean(false);  // 對象
let myBooleanLiteral = false;   // 原始布爾值,而非對象

let myObject = new Object();
let myObjectLiteral = {};

let myArray = new Array('foo','bar');
let myArrayLiteral = ['foo','bar'];

let myFunction = new Function();
let myFunctionLiteral = function () {};

let myRegExp = new RegExp();
let myRegExpLiteral = /\bt[a-z]+\b/;

// 驗證建立 自一樣的構造函數的字面量

console.log(myNumber.constructor, myNumberLiteral.construtor);
console.log(myString.constructor, myStringLiteral.construtor);
console.log(myBoolean.constructor, myBooleanLiteral.construtor);
console.log(myObject.constructor, myBooleanLiteral.construtor);
console.log(myArray.constructor, myArrayLiteral.construtor);
console.log(myFunction.constructor, myFunctionLiteral.construtor);
console.log(myRegExp.constructor, myRegExpLiteral.construtor);

// 都將輸出對象,undefined。
  • 在針對字符串、數字和布爾值使用字面量值時,只有在該值被視爲對象的狀況下才會建立實際的複雜對象。

原始值(或簡單值)

  • 數值、字符串、boolean、null、undefined等JavaScript值被視爲原始值。由於他們是不可細化的。
let myString = 'string';
let myNumber = 10;
let myBoolean = false;
let myNull = null;
let myUndefined = undefined;

console.log(myString,myNumber,myBoolean,myNull,myUndefined);

// 假設一個像數組或對象這樣的複雜對象能夠由多個原始值組成,變成一個複雜的多值集

let myObject = {
    myString: 'string',
    myNumber: 10,
    myBoolean: false,
    myNull: null,
    myUndefined: undefined
}

console.log(myObject)

let myArray = ['string', 10, false, null, undefined]

console.log(myArray)
  • 原始值是表示JavaScript中可用的數據/信息的最底層形式(即最簡單形式)

null、undefined、'string'、十、true和false等原始值不是對象

  • 原始值的特殊之處在於他們是用於表示簡單值。

如何存儲和賦值原始值

  • 原始值是做爲不可細化的值進行存儲和操做的。引用他們會轉移其值。
  • 原始值的賦值與存儲是會從新指向值的引用地址,而複雜值則不會更改引用地址
let myString = 'foo';   // 建立原始值字符對象
let myStringcopy = myString;    // 複製字符並存儲到新變量上

let myString = null;    //  操做存儲在myString變量中的值

/*
*原來的值從myString賦值到了myStringcopy上,更新myString後,再檢測myStringcopy可證明
*/

console.log(myString, myStringcopy);    // 輸出null, foo

原始值比較 採用 值比較

  • 能夠經過比較原始值來肯定其值在字面量上是否相同。
let price1 = 10;
let price2 =10;
let price3 = new Number('10');  // 複雜數字對象,由於使用了new
let price4 = price3

console.log(price1 === price2); // 輸出true

// 輸出false,由於price3包含了複雜數字變量,而price1是原始值
console.log(price1 === price3)

// 輸出true,由於複雜對象採用引用比較,而不是值比較
console.log(price3 === priec4)

// 若是price4的值爲原始值
price4 = 10;
console.log(price4 === price3); // false,price4此刻是原始值,而非複雜對象

原始值(String,Number,Boolean)在被用做對象時就像對象

  • 原始值被看成構造函數建立的一個對象來使用時,JavaScript會將其轉換爲一個對象,以即可以使用對象的特性,然後拋棄對象性質,並將它變回原始值。
// 生成原始值
let mynull = null
let myUndefined = undefined;
let primitiveString1 = 'foo';
let primitiveString2 = String('foo')
let primitiveNumber1 = 10;
let primitiveNumber2 = Number('10')

// 把原始值當對象使用時,原始值就會轉化爲對象

// 輸出string string
console.log(primitiveString1.toString(), primitiveString2.toString())

複雜值(或組合值)

  • 原生對象構造函數Object()、Array()、Function()、Date()、Error()、RegExp()是複雜類型,由於它們包含一個或多個原始值或複雜值。
  • 本質上,複雜值能夠由不少不一樣類型的JavaScript對象組成。
// 簡單的原始值,原始值不能表明複雜值,而複雜值能夠封裝成任意JavaScript值
let myString = 'string';
let myNumber = 10;
let myBoolean = false;
let myNull = null;
let myUndefined = undefined;

console.log(myString,myNumber,myBoolean,myNull,myUndefined);

// 假設一個像數組或對象這樣的複雜對象能夠由多個原始值組成,變成一個複雜的多值集

let myObject = {
    myString: 'string',
    myNumber: 10,
    myBoolean: false,
    myNull: null,
    myUndefined: undefined
}

console.log(myObject)

let myArray = ['string', 10, false, null, undefined]

console.log(myArray)
  • 複雜值是各類值的組合,而且在複雜性和組合方面與原始值不一樣。

如何存儲或複製複雜值

  • 複雜值是經過引用進行存儲和操做的
  • 建立一個包含複雜對象的變量時,其值是內存中的一個引用地址。
  • 引用一個對象時,使用它的名稱(即變量或對象屬性)經過內存中的引用地址獲取該對象值
let myObject = {}
let copyOfMyObject = myObject;  // 沒有複製值,而是複製了引用

myObject.foo = 'bar'    // 操做myObject中的值

// 輸出myObject和copyOfMyObject的值,則均會輸出foo屬性,由於他們引用的是同一個地址
console.log(myObject,copyOfMyObject);   // 輸出 Object{foo='bar'}
  • 複雜值的內存引用地址未改變,因此都指向的同一個內存地址,由於都會改變
  • 當更改複雜值時,全部引用相同地址的變量的值都會被修改,由於複雜值是經過引用進行存儲的。

複雜對象比較 採用 引用比較

  • 複雜對象只有在引用相同的對象(即有相同的地址)時才相等。
let objectFoo = { same: 'same' }
let objectBar = { same: 'same' }

// 輸出false,JS並不關注他們的類型是否相同
console.log(objectFoo === objectBar)

// 複雜對象如何才相等
let objectA = {foo: 'bar'};
let objectB = objectA;

console.log(objectA === objectB);   // true,由於他們引用的是同一個內存地址
  • 指向內存中複雜對象的變量,只有在引用相同‘地址’的狀況下才是相等的。相反,兩個單首創建的對象,即便具備相同的類型並擁有徹底相同的屬性,他們也是不相等的。

複雜對象具備動態屬性

  • 複雜對象能夠根據需求有任意多個引用,即便對象改變,他們也總指向同一個對象。
let objA = {property: 'value'};
let pointer1 = objA;
var pointer2 = pointer1;

// 更新objA.property,全部引用都會被更新了
ObjA.property = null;

// 輸出‘null null null',由於objA,proter1,proter2引用的都是同一對象.
console.log(objA.property,proter1.property,proter2.property)

typeof操做符

  • typeof操做符用於返回正在使用的類型。

構造函數實例都擁有指向其構造函數的Constructor屬性

  • 任何對象實例化時,都是在幕後將constructor屬性建立爲對象/實例的屬性。這是指建立對象的構造函數。
let foo = {};
coonsole.log(foo.constructor === Object);   // 輸出true 由於object()構建了foo

console.log(foo.constructor);   // 指向object()構造函數

驗證對象是否時特定構造函數的實例

  • 是痛instanceof操做符,能夠肯定(true或false)一個對象是不是特定構造函數的實例。
  • instanceof只適用與構造函數建立返回的複雜對象和實例
// 用戶自定義對象構造函數
let CustomConstructor = function () {this.foo = 'bar'};

// 初始化CustomConstructor的實例
let instanceOfCustomObject = new CustomConstructor();

// 輸出true
console.log(instanceOfCustomObject instanceof CustomConstructor);

// 原生對象亦是如此
console.log(new Array('foo') instanceof Array)  // 輸出true

構造函數建立的實例可擁有本身獨立的屬性(實例屬性)

let myArray = new Array();
myArray.prop = 'test';
console.log(myArray.prop); //  輸出‘test'
相關文章
相關標籤/搜索