關注物件的創造過程,很容易搞混。
一個物件可以取得或使用另外一個物件的屬性與方法。
in C#, Java
in JavaScript
JavaScript 中, 每一個物件(用 obj 表示)都有一個 proto 屬性, proto 它也是一個物件, 代表的就是 obj 的 prototype。
同時因為 proto 也是物件, 它也會有自己的 proto, 這樣一層一層串連下去就稱之為 prototype chain。
obj 可以使用到 proto 的屬性與方法。
// 一開始執行
obj.prop1
// 沒問題,很順利的運作。
//
//
// 但是當我們要執行:
obj.prop2
// js engine 在 obj 中找不到 prop2,
// 便會往第一層 __proto__ 找。
//
// 執行
obj.prop3
// obj 找不到,
// 往第一層 __proto__ 找,找不到,
// 再往第二層 __proto__ 找。
obj 會自動連結 prototype
// 要取用 prop2 時,
// 我們當然也可以寫成
obj.__proto__.prop2
// 但是我們不需要這麼做,
// js engine 會自動往 prototype 尋找屬性與方法。
obj, obj2 皆可以存取到 prop2, prop3。
原始型別 (primitive value, primitive data type) 指的是非 object 的型別,並且不具有 methods。 在 JavaScript裡,共有六種原始型別 :
string, number, boolean, null, undefined, symbol (於 ECMAScript 2015 新推出).
大部份的時候,原始型別由程式語言最底層實作。 所有的原始型別都是不可更改的。
var person = {
fiirstName : "default",
lastName : "default",
getFullName: function(){
return this.fistName + " " + this.lastName;
}
}
var john = {
firstName : "john",
LastName : "dave"
};
// don't do this EVER, for demo purposes only!!
john.__proto__ = person;
// for...in... 遍歷整個 object
for(var prop in john){
console.log(prop + ":" + john[prop]);
}
// results:
//
// firstName:john
// lastName:dave
// getFullName:function(){
// return this.fistName + " " + this.lastName;
// }
會 log 出 getFullName, 所以我們可以得知 for in 會遍歷到 prototype 的屬性與方法。
要避免遍歷到 prototype 的話就要使用 hasOwnProperty()
:
// 將上面的 for in 改寫成
for(var prop in john){
if(john.hasOwnProperty(prop)){
console.log(prop + ":" + john[prop]);
}
}
// results:
//
// firstName:john
// lastName:dave
使用 underscore 中的 extend 方法來說明:
var jane={
address: "111 Main St.",
};
var jim={
getFirstName: function(){
return this.firstName;
}
};
// 讓 john 接受其他物件的屬性與方法
_.extend(john, jane, jim);
console.log(john);
// result:
和運用 prototype 不同, 屬性與方法是值加在 john 本身上面。