javascript - hasOwnProperty 在检查父对象属性时返回 true

标签 javascript prototypal-inheritance hasownproperty coding-efficiency

我的 JavaScript 代码:

console.clear();

function BaseClass(nname) {
  var name = nname;

  this.bc_PublicProperty = "DefaultValue_BaseClass";

  this.bc_getName = function GetName() {
    return name;
  };

  this.bc_setName = function SetName(nname) {
    name = nname;
  };
}

function SubClass(nname) {
  BaseClass.call(this, nname);

  this.sc_PublicProperty = "DefaultValue_SubClass";

  this.sc_getName = function GetName() {
    return name;
  };

  this.sc_setName = function SetName(nname) {
    name = nname;
  };
}

SubClass.prototype = Object.create(BaseClass.prototype);
SubClass.prototype.constructor = SubClass;

var bc = new BaseClass("Anton");
var sc = new SubClass("Bernd");

console.log("hasOwnProperty check on subclass object 'sc' returns true for Method 'bc_getName'");

for (var pro in sc) {
  console.log("Is " + pro + " own property of subclass:  --> " + Object.hasOwnProperty.call(sc, pro));

}

我有两个对象(BaseClass 和 SubClass)。一个使用构造函数模式从另一个继承,如 explained on MDN .
现在,当我遍历子类对象的所有属性时,它们都为 hasOwnProperty 返回 true,即使对于父方法/属性,除了构造函数。
这是否意味着在使用构造函数模式时它会中断?
当我将公共(public)属性和方法放在构造函数中时,无论是在 BaseClass 还是 SubClass 中,它们都将始终被“标记”为自己的属性/方法。当我将它们附加到各自的原型(prototype)时,hasOwnProperty 将为它们输出“false”。
无论您将公共(public)方法/属性放在原型(prototype)还是构造函数本身,它们都可以在子类中使用(--> SubClass2,--> SubClass3)。
我现在唯一能想到的,为什么要将它们附加到原型(prototype)对象,是出于效率原因,如 here 所述。 ,“定义类方法”-部分。为了不为每个构造的实例添加闭包。
值类型应该在原型(prototype)上声明,但不包括初始值依赖于构造函数参数或构造时的其他状态的实例变量。
无论它们的声明位置如何,您都可以覆盖这两个属性/函数。
同样在原型(prototype)上设置 getter 和 setter,例如设置或获取私有(private)变量,是没有意义的,因为私有(private)变量必须是公共(public)的,以便附加到原型(prototype)的 getter 和 setter 可以访问。
因此,使用 getter 和 setter 是没有意义的。您可以直接访问公共(public)变量。
我现在必须稍微调整一下我的问题:
我什么时候需要hasOwnProperty,如果实际上应该在原型(prototype)上声明公共(public) Prop /功能,这反过来将全部输出Object.hasOwnProperty(obj,"prop/func") --> false。给我一个用例,在有意义的时候使用 hasOwnProperty。

console.clear();

var l = function(v) {
  console.log(v);
};

function BaseClass(nname) {

  this.bc_nameProp = nname;
  this.bc_ownFunc = function() {
    l("bc_ownFunc of BaseClass called");
  };

  this.bc_getName = function GetName() {
    return this.bc_nameProp;
  };
}

BaseClass.prototype.bc_getName = function GetName() {
  return this.bc_nameProp;
};

BaseClass.prototype.bc_PublicProperty = "DefaultValue_BaseClass";

BaseClass.prototype.bc_setName = function SetName(nname) {
  bc_nameProp = nname;
};

function SubClass(nname) {

  BaseClass.call(this, nname);

  this.sc_setName = function SetName(nname) {
    bc_nameProp = nname;
  };

  this.bc_getName = function GetName() {
    return "xyz";
  };

}

SubClass.prototype = Object.create(BaseClass.prototype);
SubClass.prototype.constructor = SubClass;

SubClass.prototype.sc_getName = function GetName() {
  return this.bc_nameProp;
};
SubClass.prototype.sc_PublicProperty = "DefaultValue_SubClass";

var bc = new BaseClass("Anton");
var sc = new SubClass("Bernd");

l("-----  iterating over BaseClass properties  ------");
l("");
for (var pro in bc) {
  l("Is " + pro + " own property of BaseClass:  --> " + Object.hasOwnProperty.call(bc, pro));

}
l("");
l("-----  iterating over SubClass properties  ------");
l("");
for (var p in sc) {
  l("Is " + p + " own property of subclass:  --> " + Object.hasOwnProperty.call(sc, p));

}

l(bc.bc_getName());
l(sc.bc_getName());
l(sc.sc_getName());


解决方案
当我问这个问题时,我认为在 JavaScript 中使用经典继承时,我可以使用 hasOwnProperty 区分我的子类的哪些属性/函数直接属于它。这是不可能的,因为父原型(prototype)的所有属性/功能都被复制到子类的原型(prototype)中:
SubClass.prototype = Object.create(BaseClass.prototype);
使用 hasOwnProperty 时,附加到原型(prototype)的所有属性/函数都返回“false”。
如果您在 BaseClass 和 SubClass 的构造函数中声明了公共(public)属性/函数,则在为子类上的这些属性调用 hasOwnProperty 时,所有这些属性都会返回“true”。
使用以下语句将这些复制到子类:
BaseClass.call(this, nname);
因此,在迭代 SubClass 类型的 obj 的所有属性时使用 hasOwnProperty,将为原型(prototype)级别声明的所有属性/函数输出 false,为构造函数级别声明的所有属性/函数输出 true。
现在,我明白了为什么在这个用例中使用 hasOwnProperty 是没有意义的。

最佳答案

检查您是否调用 BaseClass.call(this)SubClass的构造函数,这意味着您要添加 BaseClass SubClass 的属性和函数例如,因为 thisSubClass 的一个实例.
这就是为什么hasOwnProperty返回 true对于所有属性。
错误的原型(prototype)...
归根结底,您并没有利用 JavaScript 中的原型(prototype)。
必须是某个原型(prototype)的任何实例的一部分的函数应该在原型(prototype)本身中定义。

    var A = function() {};

    A.prototype = {
       doStuff: function() {}
    };
实际上,在构造时定义函数的唯一好处是您可以确保对象始终定义一些函数/属性,但是一旦对象已经创建,您就可以确保这一点。
对我来说,以下定义属性的方式之间存在很小的差异:
var A = function() {};
var instance = new A();
instance.text = "Hello, World!";

// or...

var A = function() {
    this.text = "Hello, World!";
};

var instance = new A();
第一个代码示例定义了 text调用构造函数之后的属性,而第二个在构造函数内部执行它,但在这两种情况下都是 thisinstance是对同一对象的引用(即 A 的实例)。
使用原型(prototype),您可以确保从某个构造函数创建的所有对象都将共享相同的成员,并且这些成员将被继承和使用 prototype chain .
关于OP的更新...
OP说了很多话,但总结说:

[...] I have to adjust my question a bit now: When do I need hasOwnProperty, if actually public props/functions should be declared on the prototype, which in turn will all output Object.hasOwnProperty(obj,"prop/func") --> false. Give me a use case, when it makes sense, to use hasOwnProperty.


你走错路了...为什么在需要时问自己hasOwnProperty ?问问自己,什么时候需要可重用性较低的简单对象,或者什么时候需要实际可重用性。 hasOwnProperty与这个问题无关。
当您使用文字对象时(即使用 {} 语法声明的对象)?当你需要字典、参数映射、值对象时...这里你喜欢 hasOwnProperty因为通常您的代码接收参数将如下所示:
function X(uri, options) {
   if(typeof options != "undefined") {
       // For example, we set a default value if options has no
       // mimeType property...
       options.mimeType = options.hasOwnProperty("mimeType") ? options.mimeType : "application/json";
   }
}
你什么时候使用原型(prototype)来使用复杂的对象?当您定义行为并且您需要在您的应用程序甚至多个应用程序中重用它时,您还需要在通用需求之上添加更多行为(hello 继承)。
关于为什么使用 hasOwnProperty ...
OP说:

But why would you use "hasOwnProperty" here, if you want to check the existence of an property? Shouldn't it be: options.mimeType = options.mimeType || "application/json";


互联网上有很多代码在做`options.mimeType =

options.mimeType || "application/json", right, because in JavaScript undefinedevaluates tofalse(ifoptionsdoesn't own amimeTypeproperty returnsundefined`).


以我的拙见,我会使用 hasOwnProperty因为它返回 boolean如果它存在或者它存在并且它具有未定义的值。
例如,选项可以定义为 { mimeType: undefined }有时您想知道该属性是否存在,即使它有 undefined作为值(value)。 undefinedfalse处理是否未定义的情况,无论是否存在,执行 X 和 hasOwnProperty我想确定它是否具有该属性。
所以我为什么要使用 options.hasOwnProperty超过其他方法? .简单:因为,既然语言提供了一个工具来验证某个属性是否存在于某个对象中,我为什么需要一个技巧? object.hasOwnProperty返回 truefalse ,并且我确定该属性是否存在,即使该属性具有 undefined值(value)。
options.hasOwnProperty("mimeType")我可以抛出 Error如果它存在并且它有 undefined值(value)。为什么我更喜欢这个?因为我喜欢 fail-fast 概念:如果你给了我 undefined 的属性(property)值(value)我倾向于认为您的代码中有一些错误。定义与否,我的 friend !

关于javascript - hasOwnProperty 在检查父对象属性时返回 true,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29054218/

相关文章:

javascript - 在原型(prototype)继承期间创建了多少次父对象

javascript - 为什么 hasOwnProperty 对构造函数和实例的行为不同?

javascript - 如何直接输入按钮?

javascript - jshint es6 const if else block 错误

javascript - JS中的原型(prototype)继承以及如何获取父属性

javascript - javascript 中的继承不起作用

javascript - 哪个对象的Javascript中没有`hasOwnProperty`?

javascript - 数组过滤器返回奇怪的结果

javascript - D3 为单个 json 生成多个图

javascript - RegExp 转到 toString 然后返回时出现意外行为