JavaScript 語言核心(15)函式 prototype 特性
|
在 隱藏諸多細節的建構式 中看過一個例子: function toString() {
return '[' + this.name + ',' + this.age + ']';
}
function Person(name, age) {
this.name = name;
this.age = age;
this.toString = toString;
}
這可以解決重複建立函式實例的問題,但在全域範圍(物件)上多了個 function Person(name, age) {
this.name = name;
this.age = age;
this.toString = function() {
return '[' + this.name + ', ' + this.age + ']';
};
}
如果你知道函式在定義時,都有個 function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.toString = function() {
return '[' + this.name + ', ' + this.age + ']';
};
var p1 = new Person('Justin', 35);
var p2 = new Person('Momor', 32);
console.log(p1.toString()); // [Justin, 35]
console.log(p2.toString()); // [Momor, 32]
使用 JavaScript 在尋找特性名稱時,會先在實例上找尋有無特性,以上例而言, 如果使用 ECMAScript 5,可以透過 function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.toString = function() {
return '[' + this.name + ', ' + this.age + ']';
};
var p = new Person('Justin', 35);
console.log(Person.prototype === Object.getPrototypeOf(p)); // true
Node.js、Rhino、Nashorn 中,物件都有個「非標準」特性 function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.toString = function() {
return '[' + this.name + ', ' + this.age + ']';
};
var p = {};
p.__proto__ = Person.prototype;
Person.call(p, 'Justin', 35);
console.log(p.toString()); // [Justin,35]
console.log(p instanceof Person); // true
要注意的是,只有在查找特性,而物件上不具該特性時才會使用原型,如果你對物件設定某個特性,是直接在物件上設定了特性,而不是對原型設定了特性。例如: function Some() {}
Some.prototype.data = 10;
var s = new Some();
console.log(s.data); // 10
s.data = 20;
console.log(s.data); // 20
console.log(Some.prototype.data); // 10
在上例中可以看到,你對 你可以在任何時間點對函式的 function Some() {}
var s = new Some();
console.log(s.data); // undefined
Some.prototype.data = 10;
console.log(s.data); // 10
先前在談建構式時有提過,每個透過 function Some() {}
console.log(Some.prototype.constructor); // [Function: Some]
每個函式實例,其 例如: Object.prototype.xyz = 10;
function Some() {}
var s = new Some();
console.log(s.xyz); // 10
console.log(Object.getPrototypeOf(s) === Some.prototype); // true
var protoOfS = Object.getPrototypeOf(s);
console.log(Object.getPrototypeOf(protoOfS) === Object.prototype); // true
實例的原型物件,預設就是建構式的 你也可以使用 var arr = []; console.log(Array.prototype.isPrototypeOf(arr)); // true console.log(Function.prototype.isPrototypeOf(Array)); // true console.log(Object.prototype.isPrototypeOf(Array.prototype)); // true
如果要建立一個實例,想要令其循著某個原型鏈查找,例如,想要建立一個類似陣列的物件,但要其可循著 var arrayLike = {
'0' : 10,
'1' : 20,
'2' : 30,
length : 3
};
arrayLike.__proto__ = [];
arrayLike.map(function(elem) {
return elem * 10
})
.forEach(function(elem) {
console.log(elem);
});
不過, Object.beget = function (o) {
var F = function () {};
F.prototype = o;
return new F();
};
var arrayLike = Object.beget(Array.prototype);
arrayLike[0] = 10;
arrayLike[1] = 20;
arrayLike[2] = 30;
arrayLike.length = 3;
arrayLike.map(function(elem) {
return elem * 10
})
.forEach(function(elem) {
console.log(elem);
});
ECMAScript 5 中包括了一個 var arrayLike = Object.create(Array.prototype, {
'0' : {value : 10},
'1' : {value : 20},
'2' : {value : 30},
length : {value : 3}
});
arrayLike.map(function(elem) {
return elem * 10
})
.forEach(function(elem) {
console.log(elem);
});
Object.create = function(proto, props) {
var ctor = function(ps) {
if(ps) {
Object.defineProperties( this, ps );
}
};
ctor.prototype = proto;
return new ctor(props);
};
因此,作為一個有趣的練習,先前有個範例使用了 function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.toString = function() {
return '[' + this.name + ', ' + this.age + ']';
};
var p = Object.create(Person.prototype);
Person.call(p, 'Justin', 35);
console.log(p.toString()); // [Justin,35]
console.log(p instanceof Person); // true
|

Java 學習之路





