聊聊 JavaScript 所谓的坑

网上很多人喷 JavaScript,但是那些言论在我看来,大部分只不过是一门语言初学者,都还没正儿八经掌握一门语言之前,做出的一些不太负责任的评价。

所谓的坑,应该是那些系统入门了这门语言的人才有资格发言的。如果你连正儿八经的教程都没学过,连 JavaScript 的基本原理都不懂,就觉得自己反正是通才,想当然的瞎鸡巴写,那当然会遇到很多问题。

又或者,很多人第一门接触的动态语言就是 JavaScript,遇到了一些在动态语言中挺常见的错误,就觉得这是 JavaScript 另类的地方,这只是少见多怪罢了。JavaScript 在我看来就是一门很普通的脚本语言,很多坑其实都是合理的。

我这里不评价 JavaScript 的先进与否、好用与否、垃圾与否,那些都是立项之前就应该预研好的。我评价的是,成立了 JavaScript 项目后,在开发过程中才会暴露出来的那些反人类之处。

所谓的坑,应该同时满足几个要求:

  1. 熟手都会中招
  2. 会引发非预期行为,或者严重的性能问题
  3. 不属于易用性问题

就目前而言,能让我觉得这特么就是一个坑货的傻逼设定,还不是很多。主要是几个:

一:声明变量时一不小心漏掉 var,变量会变成全局变量

解决方法:声明 “use strict”;
(这个问题 Creator 在开发过程中遇到过几次,出现的几率很低,影响也很小)

二:return 语句后面不能直接换行,否则会返回 undefined

// 如果你有一天发现 return 语句超出了 80 个字符,想要让它另起一行,变成这样
                       
                       return 
                           obj && obj.abc;

// 那么你的返回值永远都会是 undefined,因为 return 语句在执行到回车时已经结束了。
// 后面的表达式根本就不会执行到。
// 这个错误很难暴露出来,因为可能本来就要返回 false/undefined。正确的写法:
                       
                       return obj && 
                           obj.abc;

(这个问题在 Fireball 开发过程中遇到过一次,查了我好久)

三:array.sort() 默认的比较器会把元素转换为字符串再进行比较,导致整型排序出错

// 下面的结果竟然是 [10, 8, 9]
[9, 10, 8].sort()
// 下面的结果才是 [8, 9, 10]
[9, 10, 8].sort(function (lhs, rhs) { return lhs - rhs; })

(这个问题 P 大在 Creator 开发过程中遇到过一次,后果很严重)


对我来说 JavaScript 的坑真不多,就以上几点。如果你也对这门语言有担忧,那么建议你尽早把双脚浸湿,深入去好好学,把它当成一门全新的语言。


下面内容从网友回复中整理而来:

变量提升

var flag = true;
function verify() {
  if (flag) {
    ......
    var flag = false;
  }
}
// 实际等价于:
var flag = true;
function verify() {
  var flag; // = undefined
  // 下面的if内容不会执行
  if (flag) {
    ......
    flag = false;
  }
}
14赞

先占位~~~~~

mark

在这里推荐一下《JavaScript语言精粹》

变量被重新 定义 原有值 被覆盖

从C++转过来的渣渣表示,声明变量从来不会漏掉var关键字。

return后面从来没超过80个字符,所以return后面没换过行(你不说我都不知道还有这个坑)。

array.sort从来没用过,所以以上的坑一个都没遇到过。

我遇到的坑能记起的有两个

1.刚刚接触javascript时的this,变来变去的,心里一万头草泥马呼啸而过

2.for循环里做异步操作,循环的索引用var声明而不是用let,导致异步操作里面的索引值全是一样的 :joy:

12赞

用了差不多半年javascript吧,语言本身的坑其实没什么,还是比较适合作前端的语言,本身选择没什么,只是不要换来换去就好.希望官方一直坚持下去,不要再换语言,谢谢了.

哈哈哈,逗死我了
语言这东西说不好就多练,有啥可喷的

5赞

每句代码之后加个分号能避免不少问题

AS3转过来的表示没有什么特别的…除了this有点蛋疼。当然现在用ts更爽

js 用起来挺爽的啊,我也是从c艹转过来的,用了js才算是遇到真爱了

用 let 声明变量 解决

一直let 的路过

this!!!很痛

既然浏览器的脚本语言选择了javascript , 那就说明了很多;声明let 局部挺好啊

遇到过的坑:
1、对象属性不要用箭头函数

cc.Class({
  a: ()=>{
    // 错误,访问不到
    this.b();
  }, 
  b: function(){}
});

2、对函数进行bind会返回新对象,事件监听无法取消

this.node.on('touchstart', this.onTouch.bind(this));
// 两次传递的this.onTouch.bind(this)是不同对象,内部判断===的时候是false,不能取消
this.node.off('touchstart', this.onTouch.bind(this));

3、实数不能直接比较,0.47!==2.8,通过Math.abs(0.47-2.8)<1e-6来比较相等
4、受JS单线程的影响,setInterval不精确,时间越长误差越大,要采用相对计时。
5、基本类型赋值是值拷贝,对象赋值是指针拷贝,对象传递得深的时候容易误改数据。

function modify(v) {
  v.a = "World";
}
var v = {a: "Hello"};
modify(v);
console.log(v); // {a: "World"}

6、变量提升

var flag = true;
function verify() {
  if (flag) {
    ......
    var flag = false;
  }
}
// 实际等价于:
var flag = true;
function verify() {
  var flag; // = undefined
  // 下面的if内容不会执行
  if (flag) {
    ......
    flag = false;
  }
}

7、闭包访问循环变量

for (var i = 0; i <= 10; i++) {
  this.nodes[i].on("touchstart", ()=>{
    // 总是输出node 11 touched. 循环变量var i改成let i才正确。
    console.log("node " + i + " touched.");
  }
}
10赞

每门语言都有坑
没用过、不知道、不了解、不熟悉都是坑:sweat_smile:

1赞

使用eslint你为保驾,同时保持风格统一,就连一个空格都不放过!

3赞

支持eslint,這個好用

  1. 可以的话,换TS
  2. 用let和const
  3. 用===而不是==
  4. 变量声明尽量赋值

最后,至于喷js的,您应该去了解下ecmascript标准委员会成员有哪些机构之后再来下结论。
http://www.ecma-international.org/memento/members.htm