JavaScript 的成功得益于在正确的时间出现在正确的地点。JavaScript 的兴起与浏览器的支持息息相关。你瞧,VBScript 就没这么好运气。
JavaScript 很流行,但它有先天缺陷。Brendan Eich 当初只花了 10 天时间就把 JavaScript 设计出来了,作为 JavaScript 之父,BE 如是说。
JavaScript 的不足,最明显之处是语法。
糟糕冗长的语法
可选参数和默认值
function(a, b, option) {
option = option || {};
// ...
}
上面的代码中,option 是可选参数,当没有传递时,默认值是 {}. 然而,传递的 option 值有可能是假值(falsy 值)。严格来写,得如下判断:
function(a, b, option) {
option = arguments.length > 2 ? option : {};
// ...
}
注意:option = typeof option !== 'undefined' ? option : {} 也有可能是错误的,因为传递过来的可能就是 undefined.
当不需要 b 参数,删除后,基于 arguments.length 的判断很容易导致忘记修改而出错:
function(a, option) {
option = arguments.length > 2 ? option : {};
// ...
}
如果能增加以下语法该多好呀:
function(a, b, option = {}) {
// ...
}
Let
闭包很强大,也很恼火:
for (var i=0, ilen=elements.length; i<ilen; i++) { var element = elements[i]; LIB_addEventListener(element, 'click', function(event) { alert('I was originally number ' + i); }); }
上面的代码经常在面试题中出现,解决办法是再包裹一层:
for (var i=0, ilen=elements.length; i<ilen; i++) { var element = elements[i]; (function(num) { LIB_addEventListener(element, 'click', function(event) { alert('I was originally number ' + num); }); }(i)); }
如果直接支持 let 语法该多好呀:
for (var i=0, ilen=elements.length; i<ilen; i++) { var element = elements[i]; let (num = i) { LIB_addEventListener(element, function(event) { alert('I was originally number ' + num); }); }; }
模块
模块模式是一种无奈的选择:
var event = (function() { // private variables var listeners = []; function addEventListener(f) { listeners.push(f); } function clearEventListeners() { listeners = []; } // ... // export the module's API return { addEventListener: addEventListener, clearEventListeners: clearEventListeners // ... }; }());
如果原生支持该多好呀:
module event { // private variables var listeners = []; export function addEventListener(f) { listeners.push(f); } export function clearEventListeners() { listeners = []; } // ... } (function() { import event; // ... }());
继承
JavaScript 要通过原型链来实现继承:
function Employee(first, last, position) { // call the superclass constructor Person.call(this, first, last); this.position = position; }; // inherit from Person Employee.prototype = Object.create(Person.prototype); Employee.prototype.constructor = Employee; // define an overridding toString() method Employee.prototype.toString = function() { // call superclass's overridden toString() method return Person.prototype.toString.call(this) + ' is a ' + this.position; };
如果能写成下面这样该多好呀:
class Employee extends Person { constructor(first, last, position) { super(first, last); public position = position; } update(camera) { return super.update() + ' is a ' + position; } }