總的來講js語言就是門面向對象編程的語言,對象這個概念幾乎貫穿了整個js的學習。編程
對象框架
建立對象兩種方法:(若要生成對象實例必須調用構造函數)函數
一、var obj = {name:"jer" , age:12};(在js內部調用了預設的Object()構造函數)學習
訪問:alert(obj.name);//"jer"this
alert(obj["name"]);//"jer"spa
二、var obj = new Object();prototype
obj.name="jer"; 3d
打印結果:對象
1>上述就是經過原型鏈遍歷出來object構造函數的原型對象屬性和方法blog
2> prototype指定了這個構造函數實例繼承了哪一個對象(實例)
3> obj.Object.prototype就能夠訪問到這個繼承對象下的屬性
4>_proto_:原型連接點,是實例的屬性。它的值是由prototype決定的,修改Prototype的值能夠操做這個原型鏈的指向。
重點說第二個方法:
var obj = new Object();
//Object()是一個構造函數
//obj是這個構造函數的一個實例
//這個構造函數還能夠有更多實例:var obj1 = new Object(); var obj2 = new Object();
//obj1和obj2的特性:
一、共同繼承了Object()這個構造函數的方法及屬性(object是全部對象的基本類型。因此這就是爲何不少對象有着共同的繼承屬性);
二、修改obj1實例的構造函數的屬性不會影響obj2的那個屬性(從構造函數那裏獲取來的屬性變成了這個實例的屬性,修改每一個實例上的屬性,不會互相影響)
三、它倆有着共同的原型對象:Object.prototype
四、修改obj1的原型屬性不會影響obj2
五、原型裏方法的this指向這個構造函數的實例對象
//經過打印更好理解:
打印結果:
第一個原型鏈指向了Per的原型對象,這個原型對象包括兩個屬性和一個繼承的原型對象,這個對象就是Object實例(也能夠說是Object構造函數的屬性及方法)
Per.prototype.constructor返回的是構造函數,per1.prototype返回undefined,由於prototype是構造函數的屬性
constructor是原型對象的屬性,用來指向構造函數
//還有一種封裝prototype對象屬性的寫法,這個寫法是從新編寫了原型對象:
在實例以後添加這種寫法,實例訪問不到原型對象的屬性
下面這個例子是在重寫原型對象以前建立的實例:
打印
由於實例上面沒有給屬性,因此直接向上查找打印出來構造函數的屬性,打印的內容包括構造函數內定義的屬性和原型鏈上的屬性
展開
原型鏈上的屬性有原型對象屬性name和內置屬性constructor(指向構造函數)還有個繼承的Object實例
constructor指代的構造函數包含函數自身的屬性和從新定義的原型對象(prototype屬性),應爲是在原型鏈上從新封裝了原型對象,這個新原型對象也會繼承Object
重點:後面兩個打印的都返回undefined
第一個undefined是由於,實例在重寫的原型對象以前定義的,重寫原型對象就意味着切斷了實例和原本的原型之間的聯繫,實例繼承不到新原型對象的屬性
第二個undefined是由於,prototype是構造函數的屬性
重寫:將新建實例放到重寫原型對象下面
打印:
由於實例是在重寫原型對象以後定義的,因此實例可以訪問到新原型對象裏的屬性。還有個有意思的是,這個實例繼承的構造函數的原型裏面只有重寫的原型對象的屬性,Per.prototype.name="cuz";訪問不到。
實例如果能繼承從新封裝構造函數的原型對象,那麼它的原型屬性只在這個對象裏
//深刻理解構造函數:
先來看個例子:
打印
從上述例子提取到的知識點有:
一、用構造函數名字新建立的屬性沒有用。
二、設置原型函數的屬性語句放在函數裏面仍是外面一樣有效
三、實例新建屬性放置在建立實例以後也仍是會被訪問到,(由於是全局屬性,雖然start方法是在第一個打印的實例以後調用的)
這些知識框架無所謂對象,對象裏包含屬性方法,這個屬性方法又包含對象,對象又...每一個屬性方法又有不一樣的知識結構,而後各類訪問調用各類特性,組成了js編程的一張大網,不要忘了函數其實也是個對象。構造函數和其餘函數沒有區別,只是用來生成對象實例。