关于javascript原型的奇怪问题:
(function(w){
if(!w)
return;
var TestJS = function(){
};
TestJS.prototype = {
data:{},
initData:function(){
this.data={
val_name_1 : 1,
val_name_2 : 2,
val_name_3 : "hello-3"
};
console.log(this.data);
return this;
},
TestChildJS:{
initChild:function(){
console.log(TestJS);
console.log(TestJS.data);
console.log(new TestJS().data.val_name_1);
console.log(TestJS.data.val_name_1);
}
}
};
window.TestJS = new TestJS();
})(window);
为什么' TestChildJS'无法获得' val_name_1'?
TestJS.initData();
console.log(TestJS.TestChildJS.initChild());
所以我必须编写我的代码:
(function(w){
if(!w)
return;
var TestJS = function(){
};
TestJS.prototype = {
data:{},
initData:function(){
this.data={
val_name_1 : 1,
val_name_2 : 2,
val_name_3 : "hello-3"
};
console.log(this.data);
this.TestChildJS.initParentData(this);
return this;
},
TestChildJS:{
parentData:{},
initParentData:function(parent){
this.parentData = parent.data;
return this;
},
initChild:function(){
console.log(this.parentData);
}
}
};
window.TestJS = new TestJS();
})(window);
如何使用第一种方式可以获得第二种方式的内容?
答案 0 :(得分:0)
为什么'TestChildJS'无法获得'val_name_1'?
当:
TestJS.initData();
运行,它将数据属性添加到 TestJS 对象(由window.TestJS = new TestJS()
分配的对象)。该属性不会被任何其他对象继承。
当:
console.log(new TestJS().data.val_name_1);
运行,new TestJS()
返回的对象还没有调用它的 initData 方法,所以它没有 data 属性,它没有不要从构造函数继承它(因为属性直接在构造函数本身,而不是它的原型)。
另请注意,为 this.data 分配新对象会直接在实例上创建属性,因此添加到 this.data 正在修改实例的数据对象,而不是构造函数原型中的对象。
代码中的模式(尤其是第二个模式)似乎不必要地复杂化。
答案 1 :(得分:0)
这与IIFE的范围有关。在闭包内声明的变量会影响具有相同名称的任何外部变量。由于在IIFE执行后你不再能够访问它的作用域,因此其中的TempJS将始终是一个函数构造函数 - 而不是实例化的对象。
考虑这个例子:
var i;
var func = (function(){
i = 1;
return function() {
console.log(i)
};
})();
func(i); // 1
i = 2;
func(i); // 2
如果我在闭包内重新声明i
变量,看看会发生什么:
var i = 1;
var func = (function(){
var i = 1;
return function() {
console.log(i)
};
})();
func(i); // 1
i = 2;
func(i); // 1
因此,问题的一个解决方案是在IIFE之前宣布TestJS
一次。
var TestJS;
(function(w){
if(!w)
return;
TestJS = function(){
};
// ...
TestChildJS:{
initChild:function(){
console.log(TestJS.data.val_name_1);
}
// ...
window.TestJS = new TestJS();
})(window);
TestJS.initData();
console.log(TestJS.TestChildJS.initChild()); // 1
请注意,我删除了console.log(new TestJS().data.val_name_1);
。 TestJS
不再是构造函数,因此该行将抛出。
另一种解决方案是将空函数表达式分配给闭包内的window.TestJS
,而不是var TestJS
。这样做不会创建本地TestJS
名称,因此可以防止歧义。