Welcome to our website.

JavaScript Details That Are Easy to Miss

JavaScript has a relatively low barrier to entry. Compared with C or C++, it does not force developers to deal with heavy memory management or rigid type definitions in the same way. But that does not mean the language itself is simple. In real projects, JavaScript can produce all kinds of unexpected behavior: some issues come from browser compatibility, some from the language syntax itself, and some from changes in ECMAScript standards.

Below are several details that are easy to overlook, especially when moving between ordinary scripts, strict mode, and different execution environments.

1. switch uses strict comparison for case matching

var t = event.keyCode;
switch (t) {
case '65':
    alert("Yay!");
    break;
}

When the key code is 65, the alert may not appear. The reason is that switch compares case values using strict equality, equivalent to ===.

Strict equality checks both value and type. In this example, t is a Number, while '65' is a String, so the comparison fails. The case should use a numeric value if event.keyCode is expected to be numeric.

2. In strict mode, this is not automatically window

"use strict";
var global = (function() {
    console.log(this); //undefined
})();

Sometimes code uses a variable such as global to cache the global object. In a browser this is often window; in other environments, such as Workers, there may be no window, and the global object may be represented differently, for example by self.

In strict mode, however, calling a function directly does not bind this to the global object. Inside that function, this is undefined.

One way to obtain the global object is to use Function, because code created by new Function runs in the global scope:

"use strict";
var global = (function() {
    var t = new Function("return this")();
    console.log(t);
})();

Another possible approach is to call eval through window:

"use strict";
var global = (function() {
    var t = window.eval("this");
    console.log(t);
})();

The distinction matters. If eval is called directly without window., it executes within the current function scope. JavaScript uses functions to separate scopes, so a direct eval call inside a function will not naturally return window or the global object.

There is also an important limitation with new Function: it works under the global scope chain and cannot access local variables from the surrounding function.

(function () {
    var local = 1;
    new Function("console.log(typeof local);")(); // logs undefined
}());

3. Variable hoisting can hide the value you expected

var t = "global";
function foo(){
    console.log(t); //undefined
    return;
    var t = "local";
}

This is a classic hoisting example. The var declaration inside foo is lifted to the top of the function scope, even though the assignment remains where it is. Because of that local declaration, console.log(t) does not look up the global t; it finds the local t, which has been declared but not yet assigned.

The scope relationship can be thought of like this:

[Global Scope]
    |----- t [String] undefined -> "global"
    |----- foo [Reference] [foo Scope]

[foo Scope]
    |----- t [String] undefined -> "local"

When execution enters the global scope, the program finds t and foo. It first prepares them, assigning undefined where appropriate. Then t receives the value "global", and foo points to its own function scope. Inside foo, JavaScript scans the function scope and finds another t, which is initialized as undefined before any executable statement runs.

So the function behaves as if it had been written like this:

var t = "global";
function foo(){
    var t; // 等同于 -> var t = undefined;
    console.log(t); //undefined
    return;
    var t = "local";
}

The return does not change the result; it only makes the existence of hoisting more obvious. A cleaner habit is to keep variable declarations grouped near the beginning of a function instead of scattering var throughout the body:

function foo(a, b, c) {
    var x = 1,
        bar,
        baz = "something";
}

One var, followed by a list of related declarations, is easier to read and makes hoisting less surprising.

Additional strict mode details worth remembering

Strict mode changes several behaviors that may otherwise pass silently in ordinary JavaScript. These rules are easy to run into when adding "use strict"; to existing code.

1. Variables must be declared before use

"use strict";
a=1; //缺少var语句做声明,因此报错
"use strict";
var a=b=1; //错误 b未声明

In the second example, a is declared, but b is not. Under strict mode, assigning to an undeclared variable is an error instead of creating an accidental global.

2. Function declarations are not allowed in ordinary blocks

"use strict";
(function(){
    //闭包中是允许使用函数声明语句的
    function func(){};
})();
{
    var f=function(){}; //函数声明表达式允许
    function func(){}; //函数声明语句在普通闭包中,错误
};

Function expressions are allowed, but function declaration statements inside ordinary code blocks should be treated carefully in strict mode.

3. this inside a closure does not point to the global object

"use strict";
(function(){
    alert(this); //输出undefined
})();

This is the same strict-mode rule discussed earlier: a plain function call does not automatically bind this to the global object.

4. Object properties and function parameters cannot be duplicated

"use strict";
var o={a:1,a:1}; //这个对象定义了两个a属性,因此报错
"use strict";
function func(a,a){}; //这个函数的两个形参都是a,因此报错

Duplicate names that might otherwise be tolerated become errors in strict mode.

5. eval has a scope similar to a closure

"use strict";
var a=1,b=1;
eval("var a=2");
window.eval("var b=2");
alert(a); //输出1 因为运行的a变成了eval作用域的局部变量
alert(b); //输出2 window.eval依然是全局作用域

A direct eval call in strict mode does not simply leak declarations into the surrounding global scope. Calling eval through window, however, still runs it in the global context.

6. callee and caller cannot be used

"use strict";
function func(){
    return arguments.callee; //错误 callee无法使用
};
func();

Strict mode blocks access to arguments.callee and related caller information.

7. The with statement cannot be used

"use strict";
with({});

The with statement makes scope resolution ambiguous, so strict mode disallows it.

8. Octal numeric literals cannot be used

"use strict";
var a=0999; //十进制,可以使用
var b=0123; //八禁止,无法使用

Numbers that are interpreted as octal literals are not allowed in strict mode.

9. Some ineffective operations become errors

"use strict";
var a=1;
delete a; //错误 无法删除var声明的变量
"use strict";
var o={get a(){}};
o.a=1; //错误 给只读属性赋值

In non-strict mode, operations like deleting a var-declared variable or assigning to a read-only property may fail silently. Strict mode turns them into explicit errors, which makes problems easier to notice but can also expose hidden issues in older code.

Related Posts