【问题标题】:JavaScript Objects: Why Doesn't This Work?JavaScript 对象:为什么这不起作用?
【发布时间】:2019-01-27 07:07:51
【问题描述】:

我写了以下代码。它没有给我答案,而是输出 NaN。我希望代码返回 John 和 Mark 的权重。请解释一下。

'use script';

//  Declaring variables
var infoJohn;
var infoMark;
var bmiCalculator;
var higherBmi;

bmiCalculator = function (height, mass) {
    var calculatedBmi;

    calculatedBmi = mass / (height * height);
    return calculatedBmi;
};

infoJohn = {
    name: 'John',
    mass: 85,
    height: 110,
    bmi: bmiCalculator(this.height, this.mass)
};

infoMark = {
    name: 'Mark',
    mass: 120,
    height: 85,
    bmi: bmiCalculator(this.height, this.mass)
};

console.log('Mark\'s BMI: ' + infoMark.bmi, 'John\'s BMI: ' + infoJohn.bmi, 
'\n\n');

【问题讨论】:

  • 'use strict' 而不是 'use script'
  • 这是一个上下文问题,this 不是指你认为它指的东西。
  • 他已经在@gazdagergo 之前声明了变量

标签: javascript javascript-objects


【解决方案1】:

您需要将bmiCalculator 调用包装到function,否则this 指的是全局(window) 上下文。

这应该可行:

var bmiCalculator = function(height, mass) {
  var calculatedBmi;

  calculatedBmi = mass / (height * height);
  return calculatedBmi;
};

var infoJohn = {
  name: 'John',
  mass: 85,
  height: 110,
  bmi: function() {
    return bmiCalculator(this.height, this.mass);
  }
};

var infoMark = {
  name: 'Mark',
  mass: 120,
  height: 85,
  bmi: function() {
    return bmiCalculator(this.height, this.mass);
  }
};

//higherBmi = function (h)

console.log('Mark\'s BMI: ' + infoMark.bmi(), 'John\'s BMI: ' + infoJohn.bmi(),
  '\n\n');

【讨论】:

  • 你能补充一点解释吗?
  • @VojtěchDohnal 我已经更新了我的答案。感谢您的建议。
  • 这可行,但您已将 bmi 属性更改为函数。
  • @Titus 是的,这是解决 OP 问题的方法之一。
【解决方案2】:

如果要使用this 引用对象,可以使用getters

这是一个例子:

'use strict'
//  Declaring variables
var infoJohn;
var infoMark;
var bmiCalculator;
var higherBmi;

bmiCalculator = function (height, mass) {
    var calculatedBmi;

    calculatedBmi = mass / (height * height);
    return calculatedBmi;
};

infoJohn = {
    name: 'John',
    mass: 85,
    height: 110,
    get bmi(){ 
      return bmiCalculator(this.height, this.mass);
    }
};

infoMark = {
    name: 'Mark',
    mass: 120,
    height: 85,
    get bmi(){ 
      return bmiCalculator(this.height, this.mass);
    }
};

console.log('Mark\'s BMI: ' + infoMark.bmi, 'John\'s BMI: ' + infoJohn.bmi, 
'\n\n');

与您在创建对象时尝试设置bmi 属性的示例不同,这里每次访问其中一个对象的bmi 属性时都会调用bmiCalculator 函数。

【讨论】:

    【解决方案3】:

    这应该会有所帮助:

    'use strict';
    
    //  Declaring variables
    var infoJohn;
    var infoMark;
    var bmiCalculator;
    var higherBmi;
    
    var bmiCalculator = function(height, mass) {
      return mass / (height * height);
    };
    
    var infoJohn = {
      name: 'John',
      mass: 85,
      height: 110,
      get bmi() {
        return bmiCalculator(this.height, this.mass)
      }
    };
    
    var infoMark = {
      name: 'Mark',
      mass: 120,
      height: 85,
      get bmi() {
        return bmiCalculator(this.height, this.mass)
      }
    };
    
    console.log(`Mark's BMI: ${infoMark.bmi}, John's BMI: ${infoJohn.bmi}\n\n`);

    这里有几点需要注意:

    bmiCalculator 可以简单地返回,因为它进行基本计算。 infoJohninfoMark bmi 函数现在是 getters 允许在不带括号的情况下调用它们,并且通过这种方式我们在返回 bmiCalculator 时保留 this 上下文

    最后我们使用template literals

    【讨论】:

      【解决方案4】:

      您实例化对象和使用this 的方式是个问题。您正在使用对象字面量,并且在为属性分配值时,this 指的是 window(或 Node 中的 global)。

      infoJohn = {
        ...
        bmi:  ... // here - this does not refer to infoJohn
      }
      

      您的代码可以修改为在分配其他属性之后分配 BMI 属性,以便它们在运行 bmiCalculator 函数之前存在于对象上 - 但您仍然不会使用 this

      infoJohn = {
        name: 'John',
        mass: 85,
        height: 110
      };
      infoJohn.bmi = bmiCalculator(infoJohn.height, infoJohn.mass)
      

      如果你想使用this,那么它必须在正确的上下文中。这里还有一些其他答案将 BMI 作为函数或作为 getter 提供,这可能是一种更好的方法 - 每当高度或质量发生变化时,它们总是会显示更新的 BMI。

        // as a function property
        bmi: function(){ return this.mass / (this.height*this.height) }
        // or as a getter
        get bmi(){ return this.mass / (this.height*this.height) }
      

      另一种重写现有内容的方法是采用更加面向对象的方式。例如

      var Person = function(name, mass, height){
        this.name = name
        this.mass = mass
        this.height = height
        // assign a value as a static value - does not update
        this.bmi = mass / (height * height)
      }
      
      var infoJohn = new Person('John',85,110)
      var infoMark = new Person('Mark',120,85)
      
      console.log('Mark\'s BMI: ' + infoMark.bmi, 'John\'s BMI: ' + infoJohn.bmi, '\n\n');
      
      infoMark.mass = 110
      console.log('Mark\'s new BMI: '+ inforMark.bmi) // will not update
      

      【讨论】:

      • 非常有帮助。解释也很棒。非常感谢。
      【解决方案5】:

      您正在使用以前未定义的变量!在你的变量定义之前放一个var,这样程序应该知道你在说什么。你也不能直接在你的对象中调用函数!你应该使用另一个函数来调用你想要的函数。像这样:

      var infoJohn = {
          name: 'John',
          mass: 85,
          height: 110,
          bmi: function() {
              return bmiCalculator(this.height, this.mass);
          }
      };
      

      所以你必须在那之后使用bmi作为一个函数:

      console.log('Mark\'s BMI: ' + infoMark.bmi(), 'John\'s BMI: ' + infoJohn.bmi(), '\n\n');
      

      【讨论】:

        【解决方案6】:

        使用getter函数。

        infoJohn = {
            name: 'John',
            mass: 85,
            height: 110,
            bmi: bmiCalculator(this.height, this.mass) // . <<--This is incorrect
        };
        

        这里,this 对象没有像您期望的那样指向您的infoJohn 对象。相反,它指向全局 window 对象(如果您使用的是客户端 JS)。而且,由于没有 window.heightwindow.mass 属性,它会将 undefined 作为参数传递给您 bmiCalculator 函数。对undefined 等非数值的数学运算会得到NaN。因此,你得到了同样的结果。您可以按如下方式更正此问题:

        bmiCalculator = function (height, mass) {
            var calculatedBmi;
        
            calculatedBmi = mass / (height * height);
            return calculatedBmi;
        };
        
        infoJohn = {
            name: 'John',
            mass: 85,
            height: 110,
            get bmi() { return bmiCalculator(this.height, this.mass)}
        };
        
        console.log(infoJohn.bmi);

        【讨论】:

        • @Jachi 随时欢迎您。 :) 如果您觉得有帮助,请点赞(+1)我的回答。另外,将您找到的答案批准为最合适的答案。
        【解决方案7】:

        更优雅的方式...

        const bmiCalculator = (height, mass) => mass / (height * height);
        
        const infoJohn = {
            name: 'John',
            mass: 85,
            height: 110,
            get bmi() {
                return bmiCalculator(this.height, this.mass);
            }
        };
        
        console.log(infoJohn.bmi);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-11-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多