【问题标题】:"return" and "this" in strict-mode严格模式下的“return”和“this”
【发布时间】:2018-03-24 07:01:27
【问题描述】:

是否可以在一个函数中包含“this”和“return”? 像这样?

我经常使用不同的参数调用函数。但据我了解严格模式,您必须使用“new convertSomething”为每个参数启动函数。有没有更短的方法? 谢谢

"use strict";

function convertSomething(convertSeconds){
    let minutes = Math.floor(convertSeconds / 600) % 600;
    let seconds = Math.trunc(convertSeconds % 600 / 10);
    let milliseconds = (convertSeconds % 600)%10;

    this.milliseconds = milliseconds;
    this.minutes = minutes;
    this.seconds = seconds;

    let formattedTime = minutes + ":" + seconds + "." + milliseconds;
    this.formattedTime = formattedTime;
    return formattedTime;
}

let showTime = new convertSomething(2005);

console.log(showTime.milliseconds);
console.log(showTime.formattedTime);
console.log(convertSomething(1000)); // ERROR: this is undefined
<html>
    <head>
        <meta charset="ISO-8859-1">
        <script src="returnthis.js"></script>
    </head>
    <body>
        
    </body>
</html>

【问题讨论】:

  • 你的函数应该做什么?它应该是构造函数或格式化时间——不能两者兼而有之。您可以使用一个来实现另一个。
  • 我想将毫秒转换为格式化的时间戳,但想访问单独的参数:分钟、秒和毫秒。
  • 如果你使用this,你可以像你一样简单地使用showTime.formattedTime;但是使用thisreturn 没有意义,因为您使用this 修改的对象现在已丢失在垃圾中。
  • 但是对于每个新参数我都必须用let showTime = new convertSomething(otherParam);再次启动函数不是更容易调用函数并通过return获得结果吗?
  • 对我来说,@elegal 的解决方案是分解计算转换的代码的聪明方法。如果他需要转换的详细信息,他会创建一个新对象,如果不需要,他只需调用函数并获取结果,而不需要创建一个对象来存储提供他不需要的详细信息的字段。

标签: javascript this strict


【解决方案1】:

即使这样做的原因值得怀疑,您也可以这样做this

function convertSomething(convertSeconds){
    let minutes = Math.floor(convertSeconds / 600) % 600;
    let seconds = Math.trunc(convertSeconds % 600 / 10);
    let milliseconds = (convertSeconds % 600)%10;
    let formattedTime = minutes + ":" + seconds + "." + milliseconds;
    if(this){
       this.milliseconds = milliseconds;
       this.minutes = minutes;
       this.seconds = seconds;
       this.formattedTime = formattedTime;
    }
    return(formattedTime);
}

编辑

另一个解决方案是这个:

function convertSomething(convertSeconds,details){
        let minutes = Math.floor(convertSeconds / 600) % 600;
        let seconds = Math.trunc(convertSeconds % 600 / 10);
        let milliseconds = (convertSeconds % 600)%10;
        let formattedTime = minutes + ":" + seconds + "." + milliseconds;
        if(details){
           details.milliseconds = milliseconds;
           details.minutes = minutes;
           details.seconds = seconds;
           details.formattedTime = formattedTime;
        }
        return(formattedTime);
    } 

然后你就可以调用所有的函数了:

var time = convertSomething(2500);
var details = {};
var time2 = convertSomething(1000,details);
console.log(details.minutes) // or anything else

编辑 2

一般来说,类、函数、方法是用来做一件且只做一件事的。在创建 API 的情况下,将函数同时用作函数和构造函数可能会让使用它的人感到非常困惑。由于这些原因,我给你的第二个选项可能是最好的使用方法。

【讨论】:

  • 非常感谢,这解决了问题。您能否详细说明这种方法的问题?
  • 抱歉,我没有看到您评论中的“详细说明问题”部分。我刚刚编辑了我的帖子给你一个答案:)
【解决方案2】:

现在,您的函数既是构造函数又是常规函数,这些任务是完全独立的。当你和new一起使用时,返回值被忽略(因为它是一个primitive);当你在草率模式下使用它而不使用new 时,属性会放在全局对象上并被忽略。

让函数同时完成这两项工作的清理方法是返回一个包含所有所需属性的对象和另一个用于格式化字符串的对象:

"use strict";

function convertSomething(convertSeconds) {
    let minutes = Math.floor(convertSeconds / 600) % 600;
    let seconds = Math.trunc(convertSeconds % 600 / 10);
    let milliseconds = (convertSeconds % 600)%10;
    let formattedTime = minutes + ":" + seconds + "." + milliseconds;
    
    return {
      minutes,
      seconds,
      milliseconds,
      formattedTime,
    };
}

let showTime = convertSomething(2005);

console.log(showTime.milliseconds);
console.log(showTime.formattedTime);
console.log(convertSomething(1000).formattedTime);

但是,一个函数做很多不相关的工作并不是一件的事情。我建议将此拆分为一个函数以将十进制秒数(这就是您似乎拥有的,因此其他名称 convertSecondsmilliseconds 具有误导性)转换为分钟、秒和十进制,以及一个函数格式化。

function timestampFromDeciseconds(ds) {
    return {
        minutes: Math.trunc(ds / 600),
        seconds: Math.trunc(ds % 600 / 10),
        deciseconds: ds % 10,
    };
}

function formatTimestamp(timestamp) {
    return `${timestamp.minutes}:${timestamp.seconds}.${timestamp.deciseconds}`;
}

然后你可以像这样使用它们:

"use strict";

function timestampFromDeciseconds(ds) {
    return {
        minutes: Math.trunc(ds / 600),
        seconds: Math.trunc(ds % 600 / 10),
        deciseconds: ds % 10,
    };
}

function formatTimestamp(timestamp) {
    return `${timestamp.minutes}:${timestamp.seconds}.${timestamp.deciseconds}`;
}

let showTime = timestampFromDeciseconds(2005);
console.log(showTime.deciseconds);

let otherTime = timestampFromDeciseconds(1000);
console.log(formatTimestamp(otherTime));

【讨论】:

  • 第一个对我来说看起来更合乎逻辑。非常感谢。第二个诱导写两行而不是一行。我知道它的代码更干净和“好”,但我宁愿用更少的行。
  • @egalegal:所以……你知道它更好,但你还是不想使用它?唔。 =) 您可以缩短名称并将它们塞进一行,注意:console.log(format(fromDs(1000)));
  • 抱歉,Ryan,非常感谢您的帮助。我不想听起来忘恩负义。但我不是专业程序员,我需要简单的解决方案,第二个开始让我的大脑陷入困境。
  • @elegal:哦,别担心。但我认为理解第二个是值得的——因为它在概念上更简单。不幸的是,我现在没有时间对其进行扩展,但请尝试使用每个单独的功能,或者在您选择的任何学习资源取得进展之后再回来。
猜你喜欢
  • 1970-01-01
  • 2017-01-07
  • 2018-08-07
  • 1970-01-01
  • 1970-01-01
  • 2021-11-13
  • 2013-06-02
  • 1970-01-01
  • 2014-07-24
相关资源
最近更新 更多