开发人员面临的 10 个最常见的 JavaScript 问题

起初,JavaScript 可能看起来很简单。然而,这种语言比人们最初认为的要微妙、强大和复杂得多。JavaScript 的许多微妙之处导致了一些使其无法正常工作的常见问题(我们在此讨论其中的 10 个),在成为 JavaScript 开发大师的过程中,了解和避免这些问题很重要。

今天,JavaScript 是几乎所有现代 Web 应用程序的核心。这就是为什么 JavaScript 问题和找出导致这些问题的错误是 Web 开发人员最关心的问题。

用于单页应用程序 (SPA)开发、图形和动画以及服务器端 JavaScript 平台的强大的基于 JavaScript 的库和框架并不是什么新鲜事。JavaScript 已经真正在 Web 应用程序开发领域变得无处不在,因此掌握的技能越来越重要。

起初,JavaScript 可能看起来很简单。事实上,将基本的 JavaScript 功能构建到网页中对于任何有经验的软件开发人员来说都是一项相当简单的任务,即使他们是 JavaScript 新手。然而,这种语言比人们最初认为的要微妙、强大和复杂得多。事实上,JavaScript 的许多细微之处都会导致一些常见的问题,使其无法正常工作——我们在此讨论其中的 10 个——在成为JavaScript 开发大师的过程中,了解和避免这些问题很重要。

JavaScript 问题 #1:不正确的引用this

JavaScript 开发人员对JavaScript 的this关键字不乏困惑。

随着这些年来 JavaScript 编码技术和设计模式变得越来越复杂,回调和闭包中自引用范围的激增也相应增加,这是this导致 JavaScript 问题的“/那种混乱”的相当常见的来源。

考虑这个示例代码片段:

Game.prototype.restart = function () {
    this.clearLocalStorage();
    this.timer = setTimeout(function() {
    this.clearBoard();    // What is "this"?
    }, 0);
};

执行上述代码会导致以下错误:

Uncaught TypeError: undefined is not a function

为什么?这都是关于上下文的。您收到上述错误的原因是,当您调用 时setTimeout(),您实际上是在调用window.setTimeout(). 结果,传递给的匿名函数是在对象setTimeout()的上下文中定义的,该window对象没有clearBoard()方法。

一个传统的、兼容旧浏览器的解决方案是简单地将您的引用保存this在一个变量中,然后该变量可以被闭包继承;例如:

Game.prototype.restart = function () {
    this.clearLocalStorage();
    var self = this;   // Save reference to 'this', while it's still this!
    this.timer = setTimeout(function(){
    self.clearBoard();    // Oh OK, I do know who 'self' is!
    }, 0);
};

优众影视App,一款汇聚超多片源追剧神器,免费秒播高清不卡!

或者,在较新的浏览器中,您可以使用该bind()方法传入正确的引用:

Game.prototype.restart = function () {
    this.clearLocalStorage();
    this.timer = setTimeout(this.reset.bind(this), 0);  // Bind to 'this'
};
​
Game.prototype.reset = function(){
    this.clearBoard();    // Ahhh, back in the context of the right 'this'!
};

JavaScript 问题 #2:认为存在块级作用域

正如我们的JavaScript 招聘指南中所讨论的,JavaScript 开发人员之间的一个常见混淆来源(因此也是错误的常见来源)是假设 JavaScript 为每个代码块创建一个新的范围。尽管在许多其他语言中都是如此,但在 JavaScript中却不是这样。例如,考虑以下代码:

for (var i = 0; i < 10; i++) {
    /* ... */
}
console.log(i);  // What will this output?

如果您猜测console.log()调用会输出undefined或抛出错误,那么您猜错了。信不信由你,它会输出10. 为什么?

在大多数其他语言中,上面的代码会导致错误,因为变量的“生命”(即范围)i将被限制在for块中。但是,在 JavaScript 中,情况并非如此,i即使for循环完成后变量仍保留在范围内,退出循环后仍保留其最后一个值。(顺便说一下,这种行为被称为变量提升。)

可通过关键字获得对letJavaScript 中块级作用域的支持。多年来,该let关键字已被浏览器和 Node.js 等后端 JavaScript 引擎广泛支持。

如果这对您来说是新闻,那么值得花时间阅读范围、原型等。

JavaScript 问题 #3:造成内存泄漏

如果您没有有意识地编写代码来避免它们,那么内存泄漏几乎是不可避免的 JavaScript 问题。它们的发生方式有很多种,因此我们将重点介绍其中一些更常见的情况。

内存泄漏示例 1:对已失效对象的悬空引用

考虑以下代码:

var theThing = null;
var replaceThing = function () {
  var priorThing = theThing;  // Hold on to the prior thing
  var unused = function () {
    // 'unused' is the only place where 'priorThing' is referenced,
    // but 'unused' never gets invoked
    if (priorThing) {
      console.log("hi");
    }
  };
  theThing = {
    longStr: new Array(1000000).join('*'),  // Create a 1MB object
    someMethod: function () {
      console.log(someMessage);
    }
  };
};
setInterval(replaceThing, 1000);    // Invoke `replaceThing' once every second

如果你运行上面的代码并监控内存使用情况,你会发现你有一个严重的内存泄漏,每秒泄漏一兆字节! 甚至手动垃圾收集器 (GC) 也无济于事。所以看起来我们longStr每次都在泄漏replaceThing。但为什么

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pxr007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值