JS中的严格模式(Strict Mode)

什么是严格模式?

严格模式是ECMAScript5的新特性,它是采用具有限制性JavaScript变体的一种方式,从而使代码隐式地脱离“马虎模式/稀松模式/懒散模式”(sloppy)模式。

它允许你把整个程序,或者某个函数,放置在"严格"的操作语境中。这种严格的语境会防止某些特定的操作并抛出更多的异常。

虽然ECMAScript 5 对ECMAScript 3是向下兼容的,但是在严格模式下,所有在ECMAScript 3 中不赞成使用的特性都被禁用(或抛出错误)而不是兼容。

启动严格模式有以下好处:

  1. 捕获一些编程器错误,并抛出异常

  1. 阻止进行一些相对“不安全”的操作(例如访问全局变量),抛出异常。

  1. 禁用一些让人迷惑的操作。

如何启用严格模式

在程序的开头添上这条语句即可对整段脚本启用严格模式:

'use strict'

也可以只在函数内部启用严格模式,这样就不会影响到外部

function useStrict(){
    'use strict';
    //internal code
}

启用严格模式的语句只是一段普通的字符串“use strict”,没有任何新语法。这意味着不会对就旧式浏览器造成任何负面影响。

严格模式下的脚本变化

变量和属性

1、对未定义变量的赋值将会失败,而不是把这个变量作为全局变量。

2、严格模式下:写入一个可写特性为false的属性,删除一个可配置特性为false的属性,或者添加一个可扩展性为false的属性,都会导致错误。

不在严格模式下的话,这些操作不会抛出异常,仅仅是静默失败。

//对变量、函数或者函数参数执行delete操作会导致错误
var x = 'test';
function test(arg){
    delete arg; //Error
}

delete x; //Error
delete test; //Error
eval

任何对“eval”这个名字的使用(主要意图是把eval函数指向一个变量或者是对象的属性)都是禁止的

另外,通过eval声明新变量也会无效;

'use strict'
eval("var a = false");
console.log(typeof a); //undefined

如果去掉严格模式

eval("var a = false");
console.log(typeof a); //Boolean
什么是eval?

eval()函数会将传入的字符串当做JavaScript代码进行执行。

参数:String

返回值:返回字符串中代码的返回值。如果返回值为空,则返回undefined。

那为什么使用let或者const会报错呢?

var 声明的变量和使用 function 声明的函数会修改全局作用域,里面使用 let 和 const 声明的变量不会修改全局作用域,但是会在全局环境创建新的词法作用域。(作用域的问题)

这样写就不存在作用域问题。

eval的缺点:
  1. eval() 中执行的代码只能调用 JS 解释器(Interpreter)来解释执行,无法被即时编译器(JIT Compiler)优化,eval() 中的执行的代码可能会导致 JS 引擎在已经生成的机器代码中进行变量查找和赋值,带来性能问题。(无法优化,性能问题)

  1. eval() 使用不当可能会导致里面执行的字符串容易遭受恶意修改,带来安全问题(比如 XSS 攻击)。(安全问题)

  1. 使用 eval() 会干扰代码压缩工具的行为。代码压缩工具一般会将局部变量名重命名为更短的变量名(如 a 和 b 等),以便减小代码体积。当使用了 eval() 时,由于外部的局部变量可能会被 eval() 访问到,代码压缩工具便不会对可能会被 eval() 访问到的局部变量名进行压缩,会降低代码压缩率。 (降低代码压缩率)

函数
重写arguments对象会导致报错
arguments=[]

同名参数会导致报错
(function(foo,foo){}) //Error
// 非严格模式
(function () { 
    function fn(a ,a, b){
         console.log(a,b);
     }
    fn(1,2,3)
 })();  // 结果: 2 3

// 严格模式
 (function () { 
     "use strict";
     function fn(a ,a, b){
         console.log(a,b);
     }
     fn(1,2,3)
 })(); // 报错:SyntaxError: Duplicate parameter name not allowed in this context
实参形参和arguments的分离
// 非严格模式
// arguments 会受到 形参赋值的影响;
(function(){
    function fn(a,b){
        a = 20;
        console.log(a,b);  // 20  2
        console.log(arguments[0],arguments[1]); // 20  2
    }
    fn(1,2)
})(); 

// 严格模式
(function(){
    "use strict";
    // 形参 和 arguments 之间的区别;
    // 形参是变量可以随意赋值;
    // arguments 就是对应实参的关键字获取所有的实参,进行使用,不会被改变;
    function fn(a,b){
        a = 20;
        console.log(a,b);  // 20, 2 
        console.log(arguments[0],arguments[1]);  // 1, 2  
    }
    fn(1,2)
})();
arguments 的严格使用,部分功能禁用了

淘汰了 arguments.callee(引用函数本身) 和 arguments.caller(引用调用函数)。

在非严格模式下,这两个属性一个是引用函数本身,一个是引用调用函数。而在严格模式下,这两个属性都被禁用了。

(function(){
    function fn(){
       // arguments.callee 指向了当前的函数本身;
       console.log(arguments.callee);
    }
    fn()
})();  // 结果: ƒ foo(){console.log(arguments.callee);}

(function(){
    "use strict";
    function fn(){
       // 禁用掉了大部分arguments的属性;
       console.log(arguments.callee)
    }
    fn()
})();  // 报错:TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments

未声明变量辅助

如果给一个没有声明的变量赋值,那代码在执行的时候就会抛出错误

当使用null或者undefined作为Function.prototype.call或Function.prototype.apply方法的第一个参数时,函数内部的this将会指向全局对象。而严格模式将会阻止其执行并抛出异常:
(function(){ ... }).call(null); // Exception
this指向

在非严格模式下,null 或 undefined 值会被转换为全局对象 window。

在严格模式下,函数的 this 值始终是指定的值,无论指定的是什么值。

(function(){
    function fn(){
        // this 指向 window;
       console.log(this);
    }
    fn()
})(); // 结果:Window 

(function(){
    "use strict";
    function fn(){
        // 禁用指向了 window 的 this,让 this 指向 undefined
       console.log(this);
    }
    fn()
})();  // 结果:undefined

with(){}

在严格模式下,with完全不能使用

(function(){    
    with(Math){
        // 可以省略对象前置;
        console.log(random()); // => Math.random()
        console.log(PI);  // => Math.PI
    }
})();  

// 严格模式之下禁用 with(){}
(function(){
    "use strict";
    with(Math){
        console.log(random());
        console.log(PI);
    }
})();  // 报错:Uncaught SyntaxError: Strict mode code may not include a with statement

在非严格模式下,with可以改变作用域链,他可以让他里面的代码的作用域链的最顶端变成 with 括号里面的这个对象。但是会消耗大量的效率,故而ES5为了提高效率,禁用了with语句。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值