ES5严格模式

ES5严格模式

严格模式(Strict mode)是由ECMA-262规范定义的新兴JavaScript标准,第五版发布于2009年12月。旨在改善错误检查功能并且标识可能不会延续到未来JavaScript版本的脚本。ES5严格模式是限制性更强的JavaScript变体,它与常规JavaScript的语义不同,其分析更为严格。

 

目前,除了IE6-9,其它浏览器均已支持ES5严格模式。

 

一、严格模式的使用

严格模式的使用很简单,只有在代码首部加入字符串  "use strict"。有两种应用场景,一种是全局模式,一种是局部模式。

1)全局模式
1
2
3
'use strict'
var  globalVal = 100
console.log(globalVal)

执行后输出了100,与非严格模式没什么区别。

 

2)局部模式

将"use strict"放到函数内的第一行,如下

1
2
3
4
5
6
function  func() {
     'use strict'
     var  localVal = 200
     console.log(localVal)
}
func()

执行后输出了200,与非严格模式也没用什么区别。

 

3)模块模式

如果你想定义一个模块或者一个小库,自然采用一个匿名函数自执行是不错的选择

1
2
3
4
5
~ function () {
     "use strict" ;
      
     // Define your library strictly...
}();

 

“use strict” 的位置是很讲究的,必须在首部。首部指其前面没有任何有效js代码。以下都是无效的,将不会触发严格模式。

a)“use strict” 前有代码

1
2
3
var  width = 10
'use strict'
globalVar = 100

 

b)“use strict” 前有个空语句都不行

1
2
3
;
'use strict'
globalVar = 100

1
2
3
4
5
function  func() {
     ;
     'use strict'
     localVar = 200
}

1
2
3
4
function  func() {
     ; 'use strict'
     localVar = 200
}

  

当然,“use strict”前加注释是可以的

1
2
3
// strict mode
'use strict'
globalVar = 100

1
2
3
4
5
6
function  func() {
     // strict mode
     'use strict'
     localVar = 200
}
func()

 

 

二、严格模式下的执行限制

上面举的两个例子,在严格模式中输出与普通模式没用什么区别。下面就不一样了。

 

1)不使用var声明变量严格模式中将不通过

我们知道JS是弱类型,宽松的语言。不使用var声明的变量默认转为全局变量。但在严格模式中将不允许,会报语法错误。

1
2
'use strict'
globalVal = 100

执行,Firebug提示如下

 

又如全局的for循环

1
2
3
4
'use strict'
for  (i=0; i<5; i++) {
     console.log(i)
}

这种写法在非严格模式中很危险,i 会不小心溢出成为全局变量。但在严格模式中会报错

 

局部模式

1
2
3
4
5
6
function  func() {
     'use strict'
     localVal = 200
     console.log(localVal)
}
func()

执行,Firebug报错

因此,严格模式中声明变量务必记得加一个var

 

2)任何使用'eval'的操作都会被禁止
1
2
3
4
5
6
7
8
9
'use strict'
var  obj = {}
var  eval = 3
obj.eval = 1
obj.a = eval
for  ( var  eval  in  obj) {}
function  eval() {}
function  func(eval) {}
var  func =  new  Function( 'eval' )

Firebug报错

 

3)eval作用域

JS中作用域有两种,全局作用域和函数作用域。严格模式带来了第三种作用域:eval作用域,如下

1
2
3
4
'use strict'
var  a = 10
eval( 'var a = 20; console.log(a)' )
console.log(a)

Firebug控制台依次输出了20,10。eval是在全局模式下(非函数内)的,如果不加严格模式,此时修改的是全局的a。即输出20,20。见 eval与window.eval的差别

 

4)with被禁用
1
2
3
4
'use strict'
with ({a:1}) {
     
}

Firebug报错

 

5)caller/callee 被禁用
1
2
3
4
5
6
function  func() {
     'use strict'
     arguments.callee
     arguments.caller
}
func()

Firebug报错

 

6)对禁止扩展的对象添加新属性会报错
1
2
3
4
'use strict'
var  obj = {}
Object.preventExtensions(obj)
obj.a = 1  // 报错

Firebug报错

 

7)删除系统内置的属性会报错
1
2
3
'use strict'
delete  Object.prototype     // 报错
delete  Function.prototype  // 报错

Firebug 报错

 

8)delete使用var声明的变量或挂在window上的变量报错
1
2
3
4
5
'use strict'
var  obj = {a:1}
window.a = 1
delete  obj  // 报错
delete  a    // 报错

Firebug报错

 

9)delete不可删除属性(isSealed或isFrozen)的对象时报错
1
2
3
4
'use strict'
var  obj = {a: 1}
Object.seal(obj)
delete  obj.a

Firebug报错

 

10)对一个对象的只读属性进行赋值将报错
1
2
3
4
'use strict'
var  obj = {}
Object.defineProperty(obj,  'a' , {value: 1, writable:  false })
obj.a = 2  // 报错

Firebug报错

 

11)对象有重名的属性将报错
1
2
3
4
5
'use strict'
var  obj = {
     a: 1,
     a: 2
}

Firebug报错

而在非严格模式中,后面的属性将覆盖前面的属性,即obj.a等于2。

 

12)函数有重名的参数将报错
1
2
3
4
5
'use strict'
function  func(a, a) {
     alert(a)
}
func()

Firebug报错

而在非严格模式中,后面的同名参数将覆盖前面的。

 

13)八进制表示法被禁用
1
2
'use strict'
var  num = 022

Firebug报错

 

14)arguments严格定义为参数,不再与形参绑定

先看非严格模式代码

1
2
3
4
5
function  func(a) {
     arguments[0] = 2
     alert(a)  // 2
}  
func(1)

func调用时传参为1,函数内部通过arguments修改为2,此时alert的为修改后的2。 而在严格模式中则不能被修改,如下

1
2
3
4
5
6
'use strict'
function  func(a) {
     arguments[0] = 2
     alert(a)  // 1
}  
func(1)

显示的严格的为传入的1。

 

其实有点还有点复杂,如果alert的是arguments[0],实际在严格模式中仍然被修改为2了。如下

1
2
3
4
5
6
'use strict'
function  func(a) {
     arguments[0] = 2
     alert(arguments[0])  // 2
}  
func(1)

可以参考下 仅Chrome中函数实参与形参发生关联

 

15)函数必须声明在顶层

我们知道函数声明和函数表达式是两个不同的概念。一般函数声明都在最顶层,ES5前的JS宽松,你可以写在if或for内(强烈鄙视这种写法)。当然Firefox的解析方式与其他浏览器不同,见SJ9002。而在严格模式中这些写法将直接报错

1
2
3
4
5
6
7
'use strict'
if  ( true ) {
     function  func1() { }  // 语法错误
}
for  ( var  i = 0; i < 5; i++) {
     function  func2() { }  // 语法错误
}

Firebug报错

 

16)ES5里新增的关键字不能当做变量标示符使用,如implements, interface, let, package, private, protected, public, static, yield
1
2
3
'use strict'
var  let  = 10
var  yield  = 20

Firebug报错

 

17)call/apply的第一个参数直接传入不包装为对象
1
2
3
4
5
6
'use strict'
function  func() {
     console.log( typeof  this )
}
func.call( 'abcd' // string
func.apply(1)      // number

Firebug输出如下

依次为"string","number"。而在非严格模式中call/apply将对值类型的"abcd",1包装为对象后传入,即两次输出都为"object"。

 

18)call/apply的第一个参数为null/undefined时,this为null/undefined

这里以call来示例

1
2
3
4
5
6
'use strict'
function  func() {
     console.log( this )
}
func.call(undefined)  // undefined
func.call( null )       // null

Firebug输出如下

依次是undefined,null。而非严格模式中则是宿主对象,浏览器里是window,node.js环境则是global。

 

19)bind的第一个参数为null/undefined时,this为null/undefined

bind是ES5给Function.prototype新增的一个方法,它和call/apply一样在function上直接调用。它返回一个指定了上下文和参数的函数。当它的第一个参数为null/undefined时,情形和call/apply一样,this也为null/undefined。

1
2
3
4
5
6
7
8
'use strict'
function  func() {
     console.log( this )
}
var  f1 = func.bind( null )
var  f2 = func.bind(undefined)
f1()  // null
f2()  // undefined

而在非严格模式中输出的都是window(或global)。


出处http://www.cnblogs.com/snandy/p/3428171.html


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值