Javascript对象 - “这个”未定义?

时间:2017-03-28 00:26:06

标签: javascript this

我正在为改变计算器练习编写一些Javascript。其中一个要求是使用对象构造函数;但是,我在对象的一个​​方法中访问我的对象中的属性时遇到了很多麻烦。

这是我的目标:

function Coin(intValue){
    this.intCents = null; //The property

    function setCents(intValue) { //Trying access the intCents property from within this method

        /// <summary>Sets the intCents property for this object. If the given value is invalid, then the intCents property is given NaN.</summary>
        /// <param name="intCents" type="Number">The new intCents value.</param>
        if (isValid(intValue)) {
            this.intCents = intValue; //---javascript bugs out here!---
        } else {
            console.error("Invalid value given to Coin Object.");
            this.intCents = NaN;
        }
    }

    setCents(intValue);

    function getCents() {
        /// <summary>Returns the value of intCents.</summary>
        /// <returns type="Number">The intCents value.</returns>
        return this.intCents;
    }
}

以下是我如何使用我的对象:

var objCoin;

var calculateChange = function () {
    if (objCoin != null) {
        objCoin.setCents(Number.parseInt("67"));
    } else {
        objCoin = new Coin(Number.parseInt("67"));
    }
}

我拿出了一些不必要的代码,但整体基本功能如下: 用户在文本框中输入数字,然后单击网页上的按钮。该按钮通过onclick事件调用calculateChange方法。

在calculateChange方法中,“67”通常是获取文本框值的一些代码。为了简化代码并提供传递什么类型的值的具体示例,我将其替换为“67”。

发布的内容是,假设用户输入整数...

如果我的objCoin变量没有用Coin实例实例化,那么创建一个新实例并通过Coin的构造函数传入用户的输入。如果我的objCoin被实例化,那么使用setCents方法来保存用户的输入。

这是一个截图,显示正在发生的事情以及javascript错误的位置: enter image description here

根据我的理解,问题似乎与“this”关键词有关,因为它在if语句中显然未定义。尽管如此,我认为我的代码没有任何问题。

根据我在课程中的理解,this.intCents = null;是为Coin对象创建属性的正确方法,而this.intCents将是从对象内部引用属性的正确方法。它在物体的确切位置。

我试着阅读以下问题:

'this' is undefined in JavaScript class methods似乎更多地讨论了new关键字并从已创建的对象访问属性。

How does the "this" keyword work?有很多有趣的例子;但是,我仍然没有看到我的代码中的缺陷。

访问intCents属性我在哪里出错?

这种情况下this是什么? (我相信它是对象变量objCoin)

使用的程序:

Visual Studio 2015 Enterprise

Google Chrome及其开发人员工具

2 个答案:

答案 0 :(得分:2)

您需要将函数定义为已创建对象的属性,如下所示:

function Coin(intValue){
    this.intCents = null; //The property

    this.setCents = function(intValue) { //Trying access the intCents property from within this method

        /// <summary>Sets the intCents property for this object. If the given value is invalid, then the intCents property is given NaN.</summary>
        /// <param name="intCents" type="Number">The new intCents value.</param>
        if (isValid(intValue)) {
            this.intCents = intValue; //---javascript bugs out here!---
        } else {
            console.error("Invalid value given to Coin Object.");
            this.intCents = NaN;
        }
    }

    this.setCents(intCents);

    this.getCents = function() {
        /// <summary>Returns the value of intCents.</summary>
        /// <returns type="Number">The intCents value.</returns>
        return this.intCents;
    }
}

更好:将它应用于构造函数的原型:

function Coin(intValue){
    this.intCents = null; //The property
    this.setCents(intCents);

}

Coin.prototype.setCents = function(intValue) { //Trying access the intCents property from within this method

        /// <summary>Sets the intCents property for this object. If the given value is invalid, then the intCents property is given NaN.</summary>
        /// <param name="intCents" type="Number">The new intCents value.</param>
        if (isValid(intValue)) {
            this.intCents = intValue; //---javascript bugs out here!---
        } else {
            console.error("Invalid value given to Coin Object.");
            this.intCents = NaN;
        }
    }

    Coin.prototype.getCents = function() {
        /// <summary>Returns the value of intCents.</summary>
        /// <returns type="Number">The intCents value.</returns>
        return this.intCents;
    }

您所做的是:您创建了一个名为的函数(与创建变量类似,但不完全相同)。此定义发生在构造函数中,因此其“可见性”仅限于该函数的边界。此行为实际上用于模拟私有属性或方法(即使在ES6中,内部也是如此)。因此难怪该功能无法从外部访问。

现在谈到“this关键字如何运作”部分:

this始终访问绑定对象的属性。您可以使用function.bind方法将任何对象绑定到函数,在该函数内,this绑定到该对象。此外,您可以使用function.bind 功能应用于特定对象,但通常情况下,在使用new关键字时会为您完成此操作:

var x = new Coin( 3 );

new创建一个对象并将函数Coin应用于它。稍后将该新对象分配给名为x的变量(后面意味着:在构造函数完成执行之后)。

在构造函数中,您可以使用this访问该新对象。如果要将函数创建为该对象的方法,则需要将其分配给如下属性:

this.methodName = function( param ){ ... };

通过这样做,您可以为属性分配一个闭包(匿名函数),这使它成为一个方法。

这允许您稍后在构造函数创建的任何对象上调用该方法:

x.methodName( paramValue );

每个对象都有一个所谓的原型对象。这通常只是查找方法和属性的“后备”:如果在您的对象上找不到您尝试访问的方法或属性,则会搜索其原型对象以查找该标识符。此对象也有一个原型,因此查找将继续,直到搜索到最顶层的父级。如果仍找不到该属性,则为undefined

每个function都有一个名为prototype的属性:这不是函数本身的原型对象,而是分配给由此(构造函数)函数创建的每个对象的原型对象(使用new)。因此,通过将这些函数作为属性分配给构造函数原型,您不需要一次又一次地向每个创建的对象添加相同的方法(这意味着,每个创建的Coin - 对象都有自己的{{1方法=&gt;内存密集型),但是你只定义了一次方法,将它分配给原型对象,每个getCents的对象相同 - 用{{1创建的对象(只要您不更改原型对象,出于优化原因,您不应该这样做。)

答案 1 :(得分:1)

这可能与How does the “this” keyword work?

重复

一个函数这个通常是通过调用设置的( bind ,箭头函数是例外,但它们在这里并不相关)并且是限定为当前执行上下文(箭头函数除外,它采用其直接外部上下文的 this )。

因此,如果构造函数中的 setCents 函数被调用而未设置其 this

function setCents(intValue) {
    if (isValid(intValue)) {
        this.intCents = intValue; //---javascript bugs out here!---
    } else {
        console.error("Invalid value given to Coin Object.");
        this.intCents = NaN;
    }
}

setCents(intValue);

然后它的 this 将默认为全局对象(或在严格模式下保持未定义)。它不会成为新的实例。

getCents setCents 方法无法从构造函数外部访问,因此很可能它们应该位于构造函数的原型上,因此每个实例都会继承它们,例如

&#13;
&#13;
function Coin(intValue) {
  this.intCents = null; //The property
  // Initialise cents
  this.setCents(intValue);
}

Coin.prototype.setCents = function(intValue) {
    // isValid not provided so commented out
//  if (isValid(intValue)) {
    this.intCents = intValue; 
//    } else {
//    console.error("Invalid value given to Coin Object.");
//    this.intCents = NaN;
//  }
}

Coin.prototype.getCents = function() {
  return this.intCents;
}

var aCoin = new Coin(25);
console.log(aCoin.getCents()) // 25
aCoin.setCents(50);
console.log(aCoin.getCents()) // 50
&#13;
&#13;
&#13;