关于javascript原型

时间:2015-11-02 03:28:55

标签: javascript prototype

关于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());

console pic

所以我必须编写我的代码:

(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);

如何使用第一种方式可以获得第二种方式的内容?

2 个答案:

答案 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名称,因此可以防止歧义。