避免在构造函数中使用“this”

时间:2016-05-01 01:52:09

标签: javascript oop prototype

我正在寻找这样的结果:

var Dog = function() {
  this.tail = 1;
  var tail = this.tail;
  this.print = function() {
    console.log(tail);
  };
};

我在哪里使用

tail = this.tail;

避免在打印功能体中使用 this 关键字。然而,这种方法似乎有点hacky,我觉得他们必须是一个更好/更标准/不同的方式来做这种事情。

我希望这样做的原因是因为我需要将以前所有全局变量和函数的一些代码转换为对象构造函数,并且使用 this 关键字为所有变量添加前缀将是很多工作,并将使代码更加丑陋。

任何见解都很有用,谢谢你看看。

2 个答案:

答案 0 :(得分:1)

以下怎么样?我测试了它,它有效;)

var Dog = function() {
    this.tail = 1;
    this.print = function() {
        console.log(this.tail);
    };
};

var Dog = function() {
    var tail = 1;
    this.print = function() {
        console.log(tail);
    };
};

只有一个区别:this.tail可以在全球范围内进行编辑,var tail不能。但我不认为这是一个问题。

编辑:没有this

的访问尾部
var Dog = function() {
    var tail = 1;
    this.getTail = function() {
        return tail;
    };
    this.setTail = function(newTail) {
        tail = newTail;
    };

    this.print = function() {
        console.log(tail);
    };
};

答案 1 :(得分:1)

是的,你可以这样做。但是,您必须创建一个私有变量,然后使用object.defineProperty通过公共属性公开它。您必须知道浏览器compatibility issues。例如,IE9之前不支持object.defineProperty。

示例:

var log = function(message) {
  $('#log').append('<div>' + message + '</div>');
}

var Dog = function(aNumber) {
  //Create private variable for tail.  
  var tail = aNumber;

  //Create public property for tail.
  //BTW, it is generally bad practice to name a property the same name as a private variable.
  Object.defineProperty(this, 'tail', {
    get: function() {
      return tail;
    },
    set: function(value) {
      tail = value;
    }
  });

  log('ctor tail:' + tail);
  log('ctor this.tail:' + this.tail);

  this.print = function() {
    log('print tail :' + tail);
    log('print this.tail :' + this.tail)
  };
};

var firstDog = new Dog(1);
var secondDog = new Dog(2);

firstDog.tail = 3;
secondDog.tail = 4;

firstDog.print();
secondDog.print();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='log' />

在您的原始问题中,您在全局范围内引用了尾部。示例:

tail = this.tail;

在这种情况下,如果你实例化Dog的多个实例,每个实例将引用与this.tail不同的尾部版本。

示例:

var log = function(message) {
  $('#log').append('<div>' + message + '</div>');
}

var Dog = function(aNumber) {
  this.tail = aNumber;
  //Because tail hasn't been declared your referring to tail in global scope.  This is bad! 
  tail = this.tail;
  log('ctor tail:' + tail);
  log('ctor this.tail:' + this.tail);
  this.print = function() {
      log('print tail:' + tail);
      log('print this.tail:' + this.tail);
  };
};

var firstDog = new Dog(1);
var secondDog = new Dog(2);
firstDog.print(); //tail is 2 when you want it to be 1
secondDog.print();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='log' />

在你的更新中你宣布尾巴是这样的:

var tail = this.tail;

这确实创建了一个作用于Dog的构造函数的私有变量。但是,这将导致不一致的结果,因为tail和this.tail将保持不同的值。

示例:

var log = function(message) {
  $('#log').append('<div>' + message + '</div>');
}

var Dog = function(aNumber) {
  this.tail = aNumber;
  //Now you have tail scoped to this constructor/closure.  However, this.tail and tail will reference different variables.
  var tail = this.tail;
  log('ctor tail:' + tail);
  log('ctor this.tail:' + this.tail);
  this.print = function() {
    log('print tail :' + tail);
    log('print this.tail :' + this.tail);
  };
};

var firstDog = new Dog(1);
var secondDog = new Dog(2);

firstDog.tail = 3;
secondDog.tail = 4;

firstDog.print();
secondDog.print();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='log' />

如果您无法使用object.defineProperty,那么您可能会使用此前缀添加变量。但是,要确保它是100%安全的,您需要在构造函数中使用别名this

示例:

var log = function(message) {
  $('#log').append('<div>' + message + '</div>');
}

var Dog = function(aNumber) {
  var self = this
  self.tail = aNumber;
  log('ctor self.tail:' + this.tail);
  this.print = function() {
    log('print self.tail :' + self.tail);
  };
};

var firstDog = new Dog(1);
var secondDog = new Dog(2);

firstDog.tail = 3;
secondDog.tail = 4;

firstDog.print();
secondDog.print();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='log' />

顺便说一下,John Resig汇集了一个很棒的resource来更好地理解JavaScript,包括变量范围。我强烈推荐这样做。