# 严格模式和非严格模式区别

严格模式下更容易写出“安全”的JavaScript。来看看严格模式下和非严格模式下有什么区别。

# 1. 必须显式创建全局变量。

a = 7;
console.log(a); // 7
'use strict';
a = 7; // Uncaught ReferenceError: a is not defined
console.log(a);

# 2. 严格模式会使引起静默失败的赋值操作抛出异常。

"use strict";
    
// 给不可写属性赋值
var obj1 = {};
Object.defineProperty(obj1, "x", { value: 42, writable: false });
obj1.x = 9; // 抛出TypeError错误
    
// 给只读属性赋值
var obj2 = { get x() { return 17; } };
obj2.x = 5; // 抛出TypeError错误
    
// 给不可扩展对象的新属性赋值
var fixed = {};
Object.preventExtensions(fixed);
fixed.newProp = "ohai"; // 抛出TypeError错误

# 3. 试图删除不可删除或变量、函数、函数参数的属性时会抛出异常。

"use strict";
delete Object.prototype; // 抛出TypeError错误
let a = function(){};
delete a; // SyntaxError

# 4. 严格模式要求函数的参数名唯一。

function sum(a, a, c) { // !!! 语法错误
  "use strict";
  return a + a + c; // 代码运行到这里会出错
}

# 5. 严格模式禁止设置原始值的属性。

"use strict";
let a = '';
a.length = 3; // TypeError

# 6. 严格模式禁用 with。

"use strict";
var x = 17;
with (obj) { // !!! 语法错误
  // 如果没有开启严格模式,with中的这个x会指向with上面的那个x,还是obj.x?
  // 如果不运行代码,我们无法知道,因此,这种代码让引擎无法进行优化,速度也就会变慢。
  x;
}

# 7. 在严格模式中,调用的函数(不是方法)中的一个this值是undefined。

"use strict";
let a = function() {
    this.b = 2; // TypeError: this为undefined 非严格模式this为window
}
a();

// 以下可以执行
let b = {
    a: function() {
        this.c = 2; // this指向了b
    }
}
b.a();

# 8. 严格模式中 call apply传入null undefined保持原样不被转换为window

let a = function() {
    this.b = 2;
}
a.call(null); // 传入给this 非严格模式这是window

# 9. 严格模式中,arguments对象是传入函数内实参列表的静态副本;非严格模式下,arguments对象里的元素和对应的实参是指向同一个值的引用。

function f(a) {
  "use strict";
  a = 42;
  return [a, arguments[0]]; // 非严格模式arguments[0]也改变了
}
var pair = f(17);
console.assert(pair[0] === 42);
console.assert(pair[1] === 17);

# 10. 不再支持 arguments.callee。这个作用很小:直接给执行函数命名就可以了!

"use strict";
var f = function() { return arguments.callee; };
f(); // 抛出类型错误