title: (犀牛書)
tags: 創(chuàng)建對象,對象直接量,new創(chuàng)建對象 ,原型,Object.create()
創(chuàng)建對象
- 三個方法:通過對象直接量、關(guān)鍵字new每辟、Object.create()函數(shù)創(chuàng)建對象
1.1對象直接量
- 什么是對象直接量?
由若干名/值對組成的映射表干旧,名/值對中間由冒號(:)分隔,名/值對之間用逗號(妹蔽,)分隔椎眯,整個映射表用花括號({})括起來 。如:
var student = {
name: 'xiaoming',
age: 12,
isStudent: true
};
其中屬性名可以是:標識符 / 字符串直接量(包含空字符串)
屬性值可以是: 任意類型的js表達值(表達式的值可以是原始值胳岂,也可以是對象值)
var empty = {}; //沒有任何屬性的對象
var point = {x: 0, y: 0}; //有兩個屬性的對象
var point = {x: point.x, y: point.y+1}; //一個更復(fù)雜的值
var book = {
"main title": "helloJS"编整, //1
"sub-title": "The Definitive Guide", //2
"for": "all audiences", //3
author: {
firstname: "David",
surname: "Flanagan"
}
};
- 注意,上面代碼中標注1,2,3 的地方乳丰。 屬性名分別是用字符串來表示的掌测,為什么?
- "main title" 屬性名字里含有空格产园,必須使用字符串表示
- "sub-title" 屬性名字里含有連字符汞斧,必須使用字符串
- "for" 屬性名字里含有保留字,必須使用字符串
- 對象直接量的特點
對象直接量是一個表達式
這個表達式每次運算都會創(chuàng)建 并初始化 一個 新的對象
每次計算對象直接量的時候什燕,也都會計算它的每個屬性值
所以粘勒,在一個重復(fù)調(diào)用函數(shù)體中,的循環(huán)體內(nèi)屎即,使用了對象直接量,它將創(chuàng)建很多新對象庙睡,并且每一次創(chuàng)建的對象的屬性值也有可能不一樣。
1.2通過new創(chuàng)建對象
關(guān)鍵字new后跟隨一個函數(shù)調(diào)用(這里的函數(shù)成為:構(gòu)造函數(shù))技俐,就可以創(chuàng)建并初始化一個新對象乘陪。之后賦值給一個變量(一變以后的調(diào)用)。
這里的構(gòu)造函數(shù)用于初始化一個新創(chuàng)建的對象雕擂。
js中的原始類型————都包含內(nèi)置構(gòu)造函數(shù)啡邑。如:
var o = new Object(); //創(chuàng)建一個空對象,與{}一樣
var a = new Array(); //創(chuàng)建一個空數(shù)組捂刺,與[]一樣
var d = new Date(); //創(chuàng)建一個可以表示當前時間的對象
var r = new RegExp("js") //創(chuàng)建一個可以進行匹配模式的RegExp對象
1.3原型
- 每一個js對象(null除外)都和另一個對象相關(guān)聯(lián)谣拣,“另一個”對象就是我們熟知的————原型。每一個對象都從原型繼承屬性族展。
- 所有通過對象直接量創(chuàng)建的對象都具有同一個原型對象森缠,并可以通過
Object.prototype
獲得對原型對象的引用。
- 通過關(guān)鍵字new和構(gòu)造函數(shù)調(diào)用創(chuàng)建的對象的原型就就是——構(gòu)造函數(shù)的
prototype
屬性的值仪缸。
因此贵涵,通過new Object()
創(chuàng)建的對象繼承自Object.prototype
,通過new Array()
創(chuàng)建的對象的原型就是Array.prototype
,通過new Date()
創(chuàng)建的對象的原型就是Date.prototype
。
注意:1.
Object.prototype
是一個沒有原型的對象选泻,它不繼承任何屬性拉盾。其余的對象都是普通對象畅卓,普通對象都具有原型举哟。- 所有的內(nèi)置構(gòu)造函數(shù)(以及大部分自定義的構(gòu)造函數(shù))都有一個繼承自
Object.prototype
的原型助赞。
- 所有的內(nèi)置構(gòu)造函數(shù)(以及大部分自定義的構(gòu)造函數(shù))都有一個繼承自
例如:Date.prototype
的屬性————繼承自————Object.prototype
.
因此由new Date
創(chuàng)建的Date對象的屬性兼犯,同時繼承自————Date.prototype和Object.prototype
1.4 Object.create()
ES5中定義了一個名為——Object.create()
的方法捂蕴,其作用是:創(chuàng)建一個新對象员淫。
Object.create(proto[, propertiesObject])
這個語法的第一個參數(shù)是:新創(chuàng)建對象的原型端盆。第二個參數(shù)是可選值怀骤,可以對對象的屬性進行操作。
通過傳入一個原型對象來創(chuàng)建一個新對象焕妙,新對象繼承自原型的屬性和方法蒋伦。
-
Object.create()
是一個靜態(tài)函數(shù),不能作為不能作為某個對象的調(diào)用方法來使用焚鹊。只需要傳入所需要的原型對象即可痕届。如:
var o = Object.create({name:xiaoming, age:16 }); //o繼承了原型的屬性name與age
- 那么,如果傳入的原型(參數(shù))是:null,會怎么樣末患?
Object.create(null);
??
首席null(空)研叫,被創(chuàng)造的新對象,沒有任何可繼承的方法與屬性璧针。如:不能與任何運算符工作蓝撇。甚至也不包括toString()方法。
var n = Object.create(null); //代碼運行返回的結(jié)果是:{}陈莽。 但是n 不繼承任何方法與屬性渤昌,
-
Object.create(proto)
方法創(chuàng)建一個新對象,會繼承自原形的屬性與方法走搁,那么如果我們想創(chuàng)建一個普通的空對象独柑,比如:通過對象直接量{}
,或new Object()
這樣的方法私植,應(yīng)該怎么辦忌栅?
只需要傳入一個
Object.prototype
即可,例如:
var o2 = Object.create(Object.prototype); //創(chuàng)建的新對象與{}和new Object一樣曲稼。
總結(jié)(一個強大的特性):
- 任意的原型都能創(chuàng)造新對象索绪。
- 任意的對象都可以被繼承給新對象。
ES3中可以用類似以下的代碼來模擬原型繼承:
(也是一個對象繼承函數(shù)的案例)
//inherit()返回一個繼承自原型對象P的屬性的新對象
//以下代碼中Object.create()是ES5的方法贫悄,需要驗證是否可用瑞驱。(特性偵查)
//如果不存在Object.create()方法,則退化使用其他方法窄坦。
function inherit(p) {
if(p == null) throw TypeError() //如果對象是null唤反,則拋出異常
if(Object.create)
return Object.create(p) //如果存在此方法優(yōu)先使用
var t = typeof p; //否則進行進一步檢查
if(t !== "object" && t !== "function") throw TypeError();
function f(){}; //定義一個空構(gòu)造函數(shù)凳寺。
f.prototype = p; //將構(gòu)造函數(shù)f的原型設(shè)置為p,函數(shù)f就繼承自p的屬性了
return new f(); //使用f()創(chuàng)建p的繼承對象
}
- inherit()與Object.create()的區(qū)別
相同點:都是以參數(shù)為原型彤侍, 返回的新對象繼承自原型的屬性肠缨。
不同點:1. inherit()不能傳入null原形來創(chuàng)建對象。 2. inherit()不能接受可選的第二個參數(shù)盏阶。
- inherit()用作:防止庫函數(shù)無意間修改那些不受你控制的對象晒奕。
因為:inherit()不是將對象直接作為參數(shù)傳入函數(shù),而是將它的繼承對象傳入函數(shù)名斟。
所以:實際上讀取的是繼承來的值吴汪。如果給繼承屬性賦值,則這些屬性只會影響繼承屬性自身蒸眠,而不是原始對象。例:
var o = {x: "don't change this value"}
library_function(inherit(o)); //防止對o的意外修改杆融。