物件的映射表示物件能夠看見與改變自己的屬性與方法,
透過物件的映射可以使用一種有用的模式來擴展物件,
透過以下程式碼來看如何使用:
var person = {
firstname: 'Default',
lastname: 'Default',
getFullName: function() {
return this.firstname + ' ' + this.lastname;
}
}
var james = {
firstname: 'James',
lastname: 'Pon',
}
// 方便展示物件的原型物件用,不推薦這樣寫
james.__proto__ = person;
for (var prop in james) {
console.log(prop + ": " + james[prop]);
}
將 proson 物件賦予 james 物件的原型物件,
透過 for in 來查看 james 物件的屬性和方法,
如果原本就有個屬性或方法則保留,
沒有的屬性或方法會往原型鏈裡往下參考到原型物件的屬性或方法
因此可以看到 原型物件的 getFullName 方法:
如果不想要把 james 物件連結到的原型物件中的屬性與方法印出來,
可以透過物件內建的 hasOwnProperty 方法來達成,
可以把迴圈中的程式碼改寫成:
for (var prop in james) {
if(james.hasOwnProperty(prop)) {
console.log(prop + ": " + james[prop]);
}
}
這樣就只會看到 james 物件自己的屬性與方法了:
如果想要把其他物件的屬性與方法加到指定的物件上,
可以透過一個叫 underscore.js 的函式庫提供的方法來快速達成,
修改剛才的程式碼:
var person = {
firstname: 'Default',
lastname: 'Default',
getFullName: function() {
return this.firstname + ' ' + this.lastname;
}
}
var james = {
firstname: 'James',
lastname: 'Pon',
}
// 方便展示物件的原型物件用,不推薦這樣寫
james.__proto__ = person;
for (var prop in james) {
if(james.hasOwnProperty(prop)) {
console.log(prop + ": " + james[prop]);
}
}
var jane = {
address: '333 Main Street',
getAddress: function() {
return this.address;
}
}
var jimmy = {
getFirstName: function() {
return "jimmy"
}
}
_.extend(james, jane, jimmy);
console.log(james);
可以看到在 james 物件中已經有其他兩個物件的屬性與方法了:
主要是透過 underscore 的 extend 方法來達成,
_ 是 underscore 的物件本身,
_.extend 則是 underscore 物件中的方法,
extend 方法的第一個傳入的參數是要擴展屬性與方法的物件,
會從其他的當作參數傳入的物件中複製屬性與方法給被當作第一個參數傳入的物件,
建議可以參考 extend 原始碼,
來看 underscore 是怎麼達成物件擴展的,這是很好的學習素材,
// Extend a given object with all the properties in passed-in object(s).
var extend = createAssigner(allKeys);
// An internal function for creating assigner functions.
function createAssigner(keysFunc, defaults) {
return function(obj) {
var length = arguments.length;
if (defaults) obj = Object(obj);
if (length < 2 || obj == null) return obj;
for (var index = 1; index < length; index++) {
var source = arguments[index],
keys = keysFunc(source),
l = keys.length;
for (var i = 0; i < l; i++) {
var key = keys[i];
if (!defaults || obj[key] === void 0) obj[key] = source[key];
}
}
return obj;
};
}
createAssigner 方法會回傳一個匿名 function,
匿名 function 中有使用到 createAssigner function 的參數,
匿名 function 使用了閉包的特性來取用 keysFunc 與 defaults 變數來用,
匿名 function 中就是把第1個物件以外的其他物件的屬性與方法添加給第1個傳入的物件的邏輯,