2016-05-15 87 views
-1

我知道局部变量dosent在测试时工作,但我不理解这个概念。为什么“this”有效并且局部变量不能?澄清将是伟大的为什么我必须使用这个和避免局部变量! 代码:在一个类的构造函数中为什么是“this required”?为什么不能使用局部变量?

function Person(job, married) { 
    var employ = job; 
    var status = married; 
    } 
    var ray = new Person("student", true); 
    console.log(ray); 
+0

只要您离开它们定义的范围,局部变量就会被销毁。 – zerkms

+2

您可以使用局部变量,但它们只能由构造函数中的代码访问。它们不是创建对象的属性。如果你想分配对象的属性,你必须引用对象本身'this.someProp = someValue'。有一些设计模式在构造函数中分配内联方法,并且这些方法可以访问构造函数中的局部变量,但这些变量不能直接从构造函数外部访问。 – jfriend00

+0

哦,属性本质上是全球性的?这就是你为什么使用这个? –

回答

1

您可以在构造函数中使用局部变量,但它们不会自动成为对象的实例变量。相反,你使用它们的方式,它们只是暂时的局部变量,就像任何函数定义中的局部变量一样。

当你这样做:

function Person(job, married) { 
    var employ = job; 
    var status = married; 
} 
var ray = new Person("student", true); 

这里是正在发生的事情:

  1. 你定义一个名为Person功能。
  2. 在该函数中,您可以定义两个名为employstatus的局部变量。
  3. 这些是函数内的正常局部变量。它们只对该函数内的代码可见。这些可能对某些事情有用,但它们不可用于该功能之外的任何代码。它们不适用于您的对象的原型方法,它们不适用于该函数之外的其他代码。事实上,如果没有某种引用关闭的参考,它们的生命周期就会有限,并且只要Person函数完成执行,它们就会消失并垃圾回收。
  4. 所以,如果你打算创建对象的成员变量的C++等价物,这并没有完成。这些变量仅用于Person()函数的持续时间,然后被处理并且没有持久存在。
  5. 然后,当您执行var ray = new Person("student", true);时,会发生以下情况。
  6. new会导致系统创建一个新对象,将值this设置为指向该新对象,然后使用两个参数调用构造函数Person
  7. 然后,您的代码将创建两个您分配两个参数的局部变量。
  8. Person()函数然后完成执行,并且处理两个局部变量,因为它们被定义的范围已完成并且被垃圾收集。
  9. 然后,您将新创建的对象分配给变量ray。这确实是一个新对象,但它没有自定义实例数据,因为没有任何内容以持久方式存储。
  10. 如果您接着执行console.log(ray),则只会看到一个空对象,而不包含默认对象实例所具有的实例数据。您的自定义数据没有存储在任何地方,因此现在已经消失。

如果您打算将这两个参数保存在持续作为对象的实例数据的某个位置,则您有几个选择。更传统的选择是使它们成为公共可访问的对象属性。你会是这样做的:

function Person(job, married) { 
    this.employ = job; 
    this.status = married; 
} 

由于this指向新创建的对象,这段代码jobmarried参数分配给新创建的对象的属性。这些属性可以通过对象上的其他方法或通过构造函数之外的任何代码来访问,如下所示:

var ray = new Person("student", true); 
console.log(ray.employ); // "student" 
console.log(ray.status); // true 

这些属性是可公开访问的。


还有一些有趣的事情,你可以与那些局部变量,可以让他们持续,创建对象后使用做。要做到这一点,你必须创建一个闭包。我认为闭包是一个函数作用域,当函数完成执行时通常会被丢弃,但由于环境的原因,函数作用域中仍然存在实时引用,所以当函数完成执行时,垃圾收集器不会丢弃函数作用域就像使用C++这种纯粹基于堆栈的语言一样。相反,它在创建对象后仍然存在并可以通过代码访问。下面是一个例子:

function Person(job, married) { 
    var employ = job; 
    var status = married; 

    this.getEmploy = function() { 
     return employ; 
    } 

    this.getStatus = function() { 
     return status; 
    } 
} 
var ray = new Person("student", true); 
console.log(ray.getEmploy()); // "student" 
console.log(ray.getStatus()); // true 

这里是在构造函数内赋值的函数创建了一个闭包。私人局部变量employstatus在Person函数的范围内仍然是私有的。但是,由于getEmploygetStatus属性现在已公开公开,并且可以在将来某个时间调用,并且这些函数引用employstatus变量,垃圾收集器意识到它无法垃圾收集employstatus变量,因此它们坚持这个新创建的Person对象的生命周期。

使用其他面向对象语言(如C++)的熟悉术语,employstatus局部变量为您提供了一些私有实例变量的功能。有些人称这为黑客,以填补Javascript无法直接提供的功能。但是,我不认为它是一种破解。该语言提供闭包作为一个非常有用的功能,可用于多种方式,这只是一种使用闭包创建私有实例数据的好处的好处。

只有公开分配的性质getEmploygetStatus可以被外界访问,但是通过调用它们,我们可以访问私有变量employstatus。如果我们在这个新模型中使用console.log(ray),我们仍然不会在那里看到employstatus,因为就控制台而言,它们仍然不是ray对象的属性。但是,由于关闭,它们可以通过ray对象上的方法唯一访问。

此外,因为一个新的封闭每次创建我们称之为Person构造,这些employstatus变量是唯一与Person对象的每个新的实例相关联。他们的行为和工作就像对象的私人成员一样。

对于这种类型的结构和一些更多的解释更多的例子,看到这个经典的论述:http://javascript.crockford.com/private.html

为什么“这个”工作和局部变量不?

除非创建某种持久闭包,否则局部变量是暂时的。只有包含函数正在执行,它们才持续存在,然后进行垃圾回收。仅仅因为它们是在你用作构造函数的函数内部声明的,并不会使它们变得特别。它们只是局部变量,除了局部变量之外没有什么魔力。

在一个类的构造函数为什么是“this required”? 澄清将是伟大的为什么我必须使用这个,并避免当地 变量!

如果你想属性分配给您的对象,它是this指向在构造你的对象所以唯一的办法分配给你的对象的属性是引用该对象为this.someProperty = xxxx。这就是语言的工作原理。在Javascript中的所有属性引用都需要一个对象作为访问的第一部分。并且,在构造函数中,新创建的对象的引用是this。这就是语言的设计。

那些来自其他一些面向对象的语言的人可能会声明一个类的实例变量,然后只是自己使用这个名称,解释器会知道它是一个实例变量名称,而不是变量名称。在其他一些语言中可能是这样。在Javascript中这不是真的。所有属性引用(无论是在构造函数中,某些方法中还是从外部作为对象的属性访问)都必须使用一个对象作为引用的基础。并且,在构造函数和方法内部,该基数是this的值。所以,this.someProperty是你如何引用当前实例的属性。

+0

非常感谢你!只是为了确保你在getemploy函数中添加了“this”,因为函数也是一个变量,所以你想让它公开,所以你使用“this”,是否正确? –

+0

@MatthewFrancis - 我不会像你这样说。对象属性可以包含任何类型的值,数字,字符串,函数引用等等。在这种情况下,它包含一个函数引用,使其成为您可以调用的对象的方法。 – jfriend00

0

认为它是这样的:

类基本上是一个对象,对不对?那么,当你声明Person的新实例时,你会说“让我们用属性x,y和z创建一个新对象。”使用“this”可以稍后访问该实例的属性,而局部变量不会被视为您的对象的属性。

0

当函数被调用为构造函数(使用关键字new)时,将创建一个新对象(实例对象),在函数原型属性的对象值上创建原型,并使用其值this设置值构造函数到刚刚创建的新实例对象。

构造函数代码可以在this(实例对象)上设置属性和方法,这是构造函数调用的返回值(...除非构造函数显式返回其他一些对象)。

如果在构造函数中定义的变量被构造函数返回后继续存在的嵌套函数访问,它们将不会被垃圾回收,因为它们仍然可以被访问。如果在构造函数返回后它们不可访问,则它们基本上被丢弃并可用于垃圾回收。

对象创建是JavaScript行为的基础:尝试查找并阅读有关构造函数的使用。

通过搜索“JavaScript中的闭包”,可以找到关于外部函数退出后嵌套函数范围内变量保留的更多信息。

相关问题