Leg*_*nds 3 javascript coding-efficiency prototypal-inheritance hasownproperty
我的JS代码:
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));
}Run Code Online (Sandbox Code Playgroud)
我有两个对象(BaseClass/SubClass),一个使用构造函数模式从另一个继承,如MDN所述.
现在,当我遍历子类对象的所有属性时,它们都为hasOwnProperty返回true,即使对于构造函数除外的父方法/属性也是如此.
这是否意味着它在使用构造函数模式时会中断?
[编辑:]当我在构造函数中放置公共属性和方法时,在BaseClass或SubClass中,它们将始终被"标记"为自己的属性/方法.当我将它们附加到相应的原型时,hasOwnProperty将为它们输出"false".
无论是将公共方法/属性放入原型还是构造函数本身,它们都可以在子类( - > SubClass2, - > SubClass3)中使用.
我现在能想到的唯一一件事,就是为什么你应该将它们附加到原型对象上,这是因为效率原因,正如这里所解释的那样,"定义类方法"-section.为了不为每个构造的实例添加闭包.
值类型应该在原型上声明,但不能用于实例变量,其初始值取决于构造函数的参数,或者在构造时的某些其他状态.无论声明的位置如何,您都可以覆盖两个props/func.
在原型上设置getter和setter,例如设置或获取私有变量,没有任何意义,因为私有变量必须是公共的,以便可以由附加到原型的getter和setter访问.因此,使用getter和setter是没有意义的,您可以直接访问公共变量.
我现在必须稍微调整一下我的问题:我什么时候需要hasOwnProperty,如果实际上公共道具/函数应该在原型上声明,那么所有输出都会反复出现Object.hasOwnProperty(obj,"prop/func") - >假.在有意义的情况下,给我一个用例来使用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());Run Code Online (Sandbox Code Playgroud)
解
当我问这个问题时,我认为,当在JavaScript中使用经典继承时,我可以使用hasOwnProperty来区分我的子类的哪些属性/函数直接属于它.这是不可能的,因为父原型的所有属性/功能都被复制到SubClass的原型
SubClass.prototype = Object.create(BaseClass.prototype);
Run Code Online (Sandbox Code Playgroud)
当使用hasOwnProperty时,附加到原型的所有属性/函数都返回"false".如果你在BaseClass和SubClass的构造函数中声明了公共属性/函数,那么当为子类上的这些属性调用hasOwnProperty时,所有这些属性都返回"true".使用以下语句将它们复制到SubClass:
BaseClass.call(this, nname);
Run Code Online (Sandbox Code Playgroud)
因此,在迭代SubClass类型的obj的所有属性时使用hasOwnProperty,将对原型级别上声明的所有属性/函数输出false,对构造函数级别上声明的所有属性/函数输出true.
现在,我理解为什么在这个用例中使用hasOwnProperty是没有意义的.感谢@MatíasFidemraizer花时间解释.
检查你调用BaseClass.call(this)上SubClass的构造,这意味着您要添加BaseClass的属性和功能,SubClass例如,因为this是实例SubClass.
这就是为什么hasOwnProperty返回true所有属性.
在一天结束时,你没有利用JavaScript中的原型.
应该在原型本身中定义必须属于某个原型的任何实例的一部分的函数.
var A = function() {};
A.prototype = {
doStuff: function() {}
};
Run Code Online (Sandbox Code Playgroud)
实际上,在构造时定义函数的唯一好处是确保对象始终定义一些函数/属性,但是一旦已经创建了对象,就确保了这一点.
对我来说,以下定义属性的方法之间存在很小的差异:
var A = function() {};
var instance = new A();
instance.text = "hello world";
// or...
var A = function() {
this.text = "hello world";
};
var instance = new A();
Run Code Online (Sandbox Code Playgroud)
第一代码示例定义一个text后而第二个做它的构造内的构造函数被称为属性,但在这两种情况下,不是this或者instance是同一对象(即参考值的实例A).
使用原型,您可以确保从某个构造函数创建的所有对象将共享相同的成员,并且将使用原型链继承和使用这些成员.
OP说了很多东西,但总结说:
[...]我现在必须稍微调整一下我的问题:我什么时候需要hasOwnProperty,如果实际上公共道具/函数应该在原型上声明,那么所有输出都会输出Object.hasOwnProperty(obj,"prop/func ") - >假.在有意义的情况下,给我一个用例来使用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";
}
}
Run Code Online (Sandbox Code Playgroud)
使用原型时使用复杂对象?当您定义行为并且需要在应用程序甚至多个应用程序中重用它时,您还需要在通用需求之上添加更多行为(hello 继承).
hasOwnProperty......OP说:
但是,如果要检查属性是否存在,为什么要在这里使用"hasOwnProperty"?不应该是:options.mimeType = options.mimeType || "应用程序/ JSON";
网上有很多代码用`options.mimeType =
options.mimeType || "application/json"
, right, because in JavaScriptundefinedevaluates tofalse(ifoptionsdoesn't own amimeTypeproperty returnsundefined`).
在我的拙见中,我会使用hasOwnProperty它,因为它返回一个boolean如果它存在或它存在并且它未定义为值.
例如,可以将选项定义为{ mimeType: undefined },有时您想知道属性是否存在,即使它具有undefined值.在undefined作为false治疗的情况下,如果它是不确定的,或者如果它存在与否,做X,并且hasOwnProperty是我想确保它具有财产或没有.
那么为什么我会使用options.hasOwnProperty其他方法呢?.简单:因为语言提供了一个工具来验证某个对象中是否存在属性,为什么我需要一个技巧?object.hasOwnProperty返回true或者false,我确定该属性是否存在,即使该属性具有undefined值.
随着options.hasOwnProperty("mimeType")我可以抛出Error,如果它存在,它有一个undefined值.为什么我更喜欢这个?因为我喜欢快速失败的概念:如果你给了我undefined有价值的财产,我倾向于认为你的代码中有一些错误.定义与否,我的朋友!