
JavaScript 語言核心(16)檢驗物件
JavaScript 語言核心(15)函式 prototype 特性 << 前情 因為 JavaScript 是動態語言,通常很少直接確認物件的型態,對於物件的操作,僅要求是否具備所需特性,而不在意所謂的類型,物件的特性偵測絕大多數情況下就足夠了。例如: if(obj.someProperty) { // 特性存在時作某些事 } 因為特性不存在的話,會傳回 如果真得確認物件的型態,有許多方式,但這些方式基本上不是提供的資訊有限,就是不能完全信任。 例如,許多場合最常看到的 你可以從物件的 function Car() {} Car.prototype.wheels = 4; function SportsCar() {} SportsCar.prototype = new Car(); SportsCar.prototype.doors = 2; var sportsCar = new SportsCar(); console.log(sportsCar.doors); // 2 console.log(sportsCar.wheels); // 4 console.log(sportsCar.constructor); // [Function: Car] 上面這個例子,是經常見到利用原型鏈查找機制,實現出繼承的效果。由於 然而,在查找 SportsCar.prototype.constructor = SportsCar; 如果忘了作這個動作,試圖透過 關於使用 注意,實例的原型物件是在建立實例之後就確立下來的,原型鏈查找特性時,是根據實例上的原型物件,而不是函式上的 function Car() { Car.prototype.wheels = 4; } function SportsCar() { SportsCar.prototype = new Car(); SportsCar.prototype.doors = 2; } var sportsCar = new SportsCar(); console.log(sportsCar.doors); // undefined console.log(sportsCar.wheels); // undefined 這是初學者常犯的錯誤。注意,物件的原型是在建立物件之後就確立下來的,所以在這行: var sportsCar = new SportsCar();
再來用實際的程式示範會更清楚,這次用非標準的 function Car() { Car.prototype.wheels = 4; } function SportsCar() { SportsCar.prototype = new Car(); SportsCar.prototype.doors = 2; } var sportsCar = new SportsCar(); console.log( Object.getPrototypeOf(sportsCar) === SportsCar.prototype ); // false 從上例中可以看到,建立實側時就設定了原型物件,而實例上的原型物件最後跟 事實上, function Car() {} function SportsCar() {} SportsCar.prototype = new Car(); var sportsCar = new SportsCar(); console.log(sportsCar instanceof SportsCar); // true console.log(sportsCar instanceof Car); // true console.log(sportsCar instanceof Object); // true 簡單地說, var arrayLike = Object.create(Array.prototype, { '0' : {value : 10}, '1' : {value : 20}, '2' : {value : 30}, length : {value : 3} }); console.log(arrayLike instanceof Array); // true 根據 函式 prototype 特性 中對 如果你想要檢驗物件原型,除了使用 console.log(Array.prototype.isPrototypeOf([])); // true console.log(Function.prototype.isPrototypeOf(Array)); // true console.log(Object.prototype.isPrototypeOf(Array.prototype)); // true
console.log(Array.prototype.isPrototypeOf([])); // true console.log(Object.prototype.isPrototypeOf([])); // true 在取得一個物件的特性時會尋找原型鏈,如果想確認特性是物件本身所擁有,或是其原型上的特性,可透過物件都具有的 var o = {x : 10}; console.log(o.hasOwnProperty('x')); // true console.log(o.hasOwnProperty('toString')); // false console.log(o.hasOwnProperty('xyz')); // false 如果特性不是物件本身擁有,而是原型鏈上可取得,則會傳回 在物件上直接使用 var o = {x : 10}; console.log(o.propertyIsEnumerable('x')); // true console.log(o.propertyIsEnumerable('toString')); // false console.log(o.propertyIsEnumerable('xyz')); // false 當然,特性不存在時就無法列舉,所以會傳回 console.log(Object.keys({x : 10, y : 20}).join(', ')); // x, y 如果想要取得物件本身的特性名稱,無論 “ 是否設為 var obj = {}; Object.defineProperties(obj, { 'name': { value : 'John', enumerable : true }, 'age': { value : 39, enumerable : false }, }); console.log(Object.keys(obj).join(', ')); // name console.log(Object.getOwnPropertyNames(obj).join(', ')); // name, age 另外,ECMAScript 規格要求 注意!在 Internet Explorer 中, |