// 建立對象 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中,方法是包含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()對象建立自定義的對象構造函數,不論是否是用於建立對象的模式,產生的最終結果一般是建立一個複雜的對象。
// 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中,大多數值(不包括原始值),都涉及到正在被建立的對象,或者是從構造函數實例化的對象。構造函數返回的對象被稱爲實例。
Math對象是一個靜態對象,而不是構造函數。咱們能夠直接使用它,而沒必要使用new關鍵字去調用。實際上Math只是一個由JavaScript設置的對象命名空間,用於存儲數學函數。
自定義的構造函數,能夠生成多個自定義對象實例。
// 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()。
構造函數從根本上來講時用於建立預配置對象的模具模版。
let myString = new String('foo'); console.log(myString); // 輸出foo{0='f',1='o',2='o'}
// 使用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中可用的數據/信息的最底層形式(即最簡單形式)
原始值的特殊之處在於他們是用於表示簡單值。
原始值是做爲不可細化的值進行存儲和操做的。引用他們會轉移其值。
原始值的賦值與存儲是會從新指向值的引用地址,而複雜值則不會更改引用地址
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此刻是原始值,而非複雜對象
原始值被看成構造函數建立的一個對象來使用時,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)
任何對象實例化時,都是在幕後將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'