如果包含变量,并且实例设置具有相同名称的属性,则属性在哪里?

时间:2014-08-18 14:33:08

标签: javascript closures encapsulation

我们大多数人都知道JavaScript没有"私有"属性,但可以通过使用闭包来模拟该行为:

var Car = function () {
    var name = 'Tesla';
    var wheelCount = 4;

    this.getName = function () {
        return name;
    };
    this.getWheelCount = function () {
        return wheelCount;
    };
    this.setName = function (newName) {
        name = newName;
    };
    this.setWheelCount = function (newCount) {
        wheelCount = newCount;
    };
};

var myCar = new Car();
console.log(myCar.name); // undefined

对于了解JavaScript闭包如何工作的人来说,这一切都是有意义的。但是,以下内容可行:

myCar.name = 'Corvette';
console.log(myCar.name); // 'Corvette'

但是如果从原型中调用函数,则仍然使用封闭变量

console.log(myCar.getName()); // 'Tesla'

当您致电myCar.name时,您正在向对象添加新属性。在this定义中声明getName(等)函数以区分Car内的name时,是否只是使用Car的全部内容声明与myCar.name

我有一种感觉,我知道答案,但我想确定。另外,我认为这对其他人掌握JavaScript封装的工作原理是非常宝贵的。

2 个答案:

答案 0 :(得分:1)

在您的示例中,car函数是一个构造函数。当使用new运算符调用构造函数时,会创建一个新对象并且"这个"绑定到该新对象。并且"这个"即使没有return语句也会从函数返回(与非构造函数不同,如果没有返回则返回undefined)

所以当你调用new Car()时,会创建一个新对象,并且#34;这个"在这个新对象中,新对象获得了你在Car函数中定义的4个函数(getName,getWheelCount,setName,setWheelCount)

Car函数中定义的名称变量不限于"这个",它与Car的功能范围有关。当汽车功能返回"这个",因为关闭getName()仍然可以访问函数的名称变量。

现在当你尝试myCar.name时,因为创建的新对象没有任何名为name的变量,所以它打印为undefined。

在执行myCar.name =' Corvette'时,由于在myCar中找不到名为name的属性,因此创建了名为" name"的新属性。和价值" Corvette" (javascript创建一个新属性,如果在写操作的情况下它还不存在,对于读操作原型链是遵循的)

但令人惊讶的是myCar.getName()仍会打印"特斯拉"而不是Corvette,因为虽然变量名是相同的,但是它们在不同的范围内.getName引用的那个是Car函数范围的一部分,并且通过Closure限制为getName,但名称(" corvette" )您添加的属于您创建的新对象。

"这个"的目的是将构造函数内定义的函数/变量添加到您将通过该构造函数创建的对象。

希望它有所帮助。

答案 1 :(得分:1)

  

this定义中声明getName(等)函数以区分{{1}中包含的名称时,是否只是使用Car的全部内容声明与Car

myCar.name(或this)是您放置属性的对象(在本例中为所有这些方法)。如果要使用属性,则必须使用property accessor

myCar只是构造函数中的本地变量,可以通过对象方法的闭包来访问。

或者,回答你的标题问题:

  

如果包含变量,并且实例设置了具有相同名称的属性,则属性在哪里?

该属性在对象上 。它根本不会干扰变量,该变量位于var name构造函数调用的范围