这是 javascript 属性 实例 属性,还是原型 属性?

Is this javascript property an instance property, or, a prototype property?

我给一个函数一个属性,然后用这个函数作为构造函数,像这样:

function h(){this.a='abc';}
h.high='2.0';
var hinst=new h();
function hasPrototypeProperty(object, name){
    return !object.hasOwnProperty(name) && (name in object);
}
console.log(h.hasOwnProperty('high'));    //true
console.log(hinst.hasOwnProperty('high'));//false
console.log(hasPrototypeProperty(hinst, 'high'));//false
console.log('a' in hinst);   //true
console.log('high' in hinst);//false
console.log(hinst.prototype.constructor.high);   //exception

很奇怪,在我的测试中,'high'既不是实例属性

hinst.hasOwnProperty)

或原型属性

hasPrototypeProperty(hinst,'high')

最后一行抛出异常说

TypeError: Cannot read property 'constructor' of undefined

我想我对属性有一些误解,'hinst'怎么能访问'high'属性?

此处 h 是一个类型为 function 的对象,您为其分配了名为 highproperty。所以它与实例或原型无关。

您的代码中构造函数和原型有些混淆

console.log(inst.prototype.constructor.high); // exception
console.log(inst.constructor.high); // '2.0'

因为你的构造函数不是原型链的一部分。
当您事后在构造函数上定义属性时(它们只是 功能)然后你最终得到这个

function h () {
this.a='abc';
}
h.high='2.0';
console.log(h);
// => { [Function: h] high: '2.0' }

一个弗兰肯斯坦函数对象怪物。

让我们分解一下。

这里创建了一个构造函数。它们旨在与 new 运算符一起使用。一个普遍的惯例是将第一个字母大写以表明该意图。

function H(){ this.a='abc'; }

当使用 new 调用构造函数时,会发生类似的情况:

(function(){
    var o = Object.create( H.prototype );
    H.apply( o, arguments );
    return o;
}());

你基本上得到了一个继承自 H.prototype 对象的新对象 ({ a: 'abc' })。也就是说,它的内部 [[Prototype]] 属性1 指向它。

H.prototype 最初是一个具有单个 属性 的对象(constructor 指向构造函数 H),但您可以自由替换或扩展它。你可能想用这一行做什么:

H.high='2.0';

但是,您将 属性 添加到构造函数 H(函数也是对象)。

console.log( H.hasOwnProperty('high') );                //true
console.log( (new H()).hasOwnProperty('high') );        //false
console.log( (new H()).hasPrototypeProperty('high') );  //false

更正示例。

function H(){ this.a='abc'; }
H.prototype.high='2.0';
var hinst = new H();
function hasPrototypeProperty(object, name){
  return !object.hasOwnProperty(name) && (name in object);
}
console.log(H.hasOwnProperty('high'));            //false
console.log(hinst.hasOwnProperty('high'));        //false
console.log(H.prototype.hasOwnProperty('high'));  //true
console.log(hasPrototypeProperty(hinst, 'high')); //true
console.log('a' in hinst);                        //true
console.log('high' in hinst);                     //true
console.log(H.prototype.high);                    //2.0
console.log(hinst.high);                          //2.0


1 Inheritance and the prototype chain at MDN