js严酷方式轻巧理解及与非严酷方式的差距【分分

作者:分分快三计划

总结

随着JS的飞速发展,出现了一大堆可以代替严格模式的工具,比如eslint等,但是,当你想要提升原生JS代码的健壮性和可读性,回避JS一些被人诟病的语法,严格模式是你不二的选择。

"use strict"
使用"use strict"指令的目的是说明(脚本或函数中)后续的代码将会解析为严格代码(strict code)。
如果顶层(不在任何函数体内)代码使用了"use strict" 指令,那么他们就是严格代码。
如果函数体定义所处的代码是严格代码或者函数体使用了"use strict"指令,那么函数体的代码也是严格代码。
严格代码以严格模式执行。ECMAScript5中的严格模式是该语言的一个受限制的子集,它修正了语言的重要缺陷,并提供健壮的查错功能和增强的安全机制。
@严格模式和非严格模式之间的区别如下:
*在严格模式中禁止使用with语句
*在严格模式中,所有的变量都要先声明,如果给一个未声明的变量、函数、函数参数、 catch从句参数或全局对象的属性赋值,将会抛出一个引用错误异常(在非严格模式中,这种隐式声明的全局变量的方法是给全局对象新添加一个新属性)。
*在严格模式中,调用的函数(不是方法)中的一个this值是undefined。(在非严格模式中, 调用的函数中的this值总是全局对象)。
可以利用这种特性来判断JavaScript实现是否支持严格模式:
var hasStrictMode = (function(){"use strict";retuen this===undefined}());
*同样,在严格模式中,当通过call()或apply()来调用函数中时,其中this值就是通过call()或apply()传入的第一个参数(在非严格模式中,null和undefined值被全局对象和转换为对象的非对象值所替代)
*在严格模式中,给只读属性赋值和给不可扩展的对象创建新成员都将抛出一个类型错误异常(在非严格模式中,这些操作只是简单地操作失败,不会报错)。
*在严格模式中,传入eval()的代码不能在调用程序所在的上下文中声明变量或定义函数,而在非严格模式中是可以这样做的。相反,变量和函数的定义是在eval()创建的新作用域中,这个作用域是在eval()返回时就弃用了。
*在严格模式中,函数里的arguments对象拥有传入函数值的静态副本。在非严格模式中,arguments对象具有“魔术般”的行为,arguments里的数组元素和函数参数都是指向同一个值的引用。
*在严格模式中,当delete运算符后跟随非法的标识符(比如变量、函数、函数参数)时,将会抛出一个语法错误异常(在非严格模式中,这种delete表达式什么也没做,并返回false)。
*在严格模式中,试图删除一个不可配置的属性将抛出一个类型错误异常(在非严格模式中,delete表达式操作失败,并返回false)。
*在严格模式中,在一个对象直接量中定义两个或多个同名属性将产生一个语法错误(在非严格模式下不会报错)
*在严格模式中,函数声明中存在两个或多个同名的参数将产生一个语法错误(在非严格模式中不会报错)
*在严格模式中是不允许使用八进制整数直接量(以0位前缀,而不是0x为前缀)的(在非严格模式中某些实现是允许八进制整数直接量的)
*在严格模式中,标识符eval和arguments当做关键字,它们的值是不能更改的。不能给这些标识符赋值,也不能把它们声明为变量、用做函数名、用做函数参数或用做catch快的标识符。
*在严格模式中限制了对调用栈的检测能力,在严格模式的函数中,arguments.caller和arguments.callee都会抛出一个类型错误异常。严格模式的函数同样具有caller和arguments属性,当访问这两个属性时将抛出类型错误异常(有一些JavaScript的实现在非严格模式里定义了这些非标准的属性)

分分快三计划 1

规则

1.严格模式下无法隐式创建全局变量

2.严格模式会使引起静默失败(silently fail,注:不报错也没有任何效果)的赋值操做抛出异常

"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错误

4.在严格模式下,不允许重名属性

"use strict";
var o = { p: 1, p: 2 }; // 语法错误

5.严格模式要求函数参数名唯一

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

6.禁止八进制数字语法

"use strict";
var sum = 015   // 语法错误
          197  
          142;

7.禁止设置原始类型(primitive)值的属性

(function() {
  "use strict";

  false.true = "";              //TypeError
  (14).sailing = "home";        //TypeError
  "with".you = "far away";      //TypeError

})();

8.禁用with

9.严格模式下,eval()创建变量不能被调用

"use strict";
eval ("var x = 2");
alert (x);                      // Uncaught ReferenceError: x is not defined

10.严格模式禁止删除声明变量

"use strict";

var x;
delete x; // 语法错误

eval("var y; delete y;"); // 语法错误

11.不能使用evalarguments字符串

"use strict";
var arguments = 1;    // Uncaught SyntaxError: Unexpected eval or arguments in strict mode
var eval = 2;         // Uncaught SyntaxError: Unexpected eval or arguments in strict mode

12.严格模式下,函数的 arguments 对象会保存函数被调用时的原始参数。arguments[i] 的值不会随与之相应的参数的值的改变而变化,同名参数的值也不会随与之相应的 arguments[i] 的值的改变而变化。

13.不再支持arguments.callee

"use strict";
var f = function() { return arguments.callee; };
f();                // TypeError

14.保留部分关键字,这些字符包括implements, interface, let, package, private, protected, public, staticyield。在严格模式下,你不能再用这些名字作为变量名或形参名。

15.禁止this指向全局对象,当this指向全局对象时,自动转为undefined

1.所有的变量都必须使用var关键字声明

非严格模式下:

a = 10;     
console.log(a);    //打印为:10

严格模式下:

"use strict";
a = 10;      //这行直接报错
console.log(a);       

用法

进入严格模式的方法很简单,只需要在在需要进入严格模式的作用域开头输入"user strict"即可,值得一提的是,在无法执行严格模式的旧版浏览器中(IE10之前),该条指令会自动被忽略。

例1:

"user strict";
x = 1;          // Uncaught ReferenceError: x is not defined

如例1所示,在全局作用域的开头定义了严格模式,并隐式定义了全局变量xx = 1 这条语句在严格模式下,抛出了异常,提示没有显式创建变量a

例2:

"use strict";
fn();

function fn () {
  x = 1;            // Uncaught ReferenceError: x is not defined
}

在例2中,由于严格模式定义在全局作用域中,而fn作用域被全局作用域所包含,所以fn作用域中同样执行了严格模式。

注:也可以通过执行上下文栈来解释。

例3:

x = 1;
fn();

function fn () {
  "use strict"
  y = 2;            // Uncaught ReferenceError: y is not defined
}

在例3中,由于严格模式只定义在fn函数的局部作用域中,在全局作用域中不起作用,所以全局作用域中,隐式定义全局变量x没有抛出异常,而在局部作用域中,隐式定义全局变量y抛出异常。

10.禁用了with语句

下面为with的使用介绍,但是再严格模式下将不再支持该方法,调用会显示报错

var o = {name:"码农x号",age:22};
with(o) {
  name = "kevin";
  age = 48
}
console.log(o);  //输出结果:{name:"kevin",age:48}

简介

何为严格模式?严格模式(strict mode)即在严格的条件下运行,在严格模式下,很多正常情况下不会报错的问题语句,将会报错并阻止运行。

但是,严格模式可以显著提高代码的健壮性,比如JS经常被人诟病的隐式创建全局变量,在严格模式下就会阻止运行。

总的来说,引入严格模式虽然会导致一些代码不可运行,但是,严格模式使得一些JS广受诟病的问题无法运行,从长期角度上看,绝对是利大于弊。

三、严格模式下的特点

浅谈JS严格模式

一、概述:

JavaScript由于语法的不严谨,一直所被人诟病。于是在ECMAscript 5添加了第二种运行模式:“严格模式”。一旦使用严格模式,那么一些“不严谨”的语法代码将不再被支持。

这样做的好处是:

  • 提早知道代码中存在的错误,即使捕获一些可能导致编程错误的ECMAScript行为。

  • 提高编译器效率,增加运行速度;

  • 为未来新版本的Javascript做好铺垫。

5.函数内的arguments对象的行为不同

说明:

  1. 在非严格模式下,修改了形参的值,arguments中的数据会跟着改变

  2. 严格模式下,在函数内部修改了对象的指向,对arguments的值不会产生影响。因为在严格模式下,形参的值和arguments的值是相互独立的,在函数内部修改了形参的值对arguments不受影响

先来看看非严格模式下,arguments与形参的关系:

//测试引用类型(对象类型)的值作为函数的参数
function funcName(obj) {
  console.log(obj);         //执行后打印为:{name:"码农一号"}
  console.log(arguments[0]);//打印为:{name:"码农一号"}
  //在函数内部修改形参的值
  obj = {age:20};       //修改形参
  console.log(obj);     //打印为:{age:20}
  console.log(arguments[0]);  //打印为:{age:20}
}
funcName({name:"码农一号"});  

//测试基本类型数据作为函数的参数
function fun(str) {
  console.log(str);         
  console.log(arguments[0]);    //上下打印都为:"hi";
  str = "hello";                //修改形参
  console.log(arguments[0]);    //打印为:"hello" 
}
fun("hi");

结论:非严格模式下,修改形参的值,arguments内的元素会跟着改变!

下面再来验证下严格模式下,形参与arguments的关系:

//声明严格模式
"use script";
//测试引用类型(对象类型)的值作为函数的参数
function funcName(obj) {
  console.log(obj);         //执行后打印为:{name:"码农一号"}
  console.log(arguments[0]);//打印为:{name:"码农一号"}
  //在函数内部修改形参的值
  obj = {age:20};       //修改形参
  console.log(obj);     //打印为:{age:20}
  console.log(arguments[0]);  //打印为:{name:"码农一号"}
}
funcName({name:"码农一号"});  

//测试基本类型数据作为函数的参数
function fun(str) {
  console.log(str);         
  console.log(arguments[0]);    //上下打印都为:"hi";
  str = "hello";                //修改形参
  console.log(arguments[0]);    //打印为:"hi" ,str的修改不影响arguments
}
fun("hi");

*结论:严格模式下,形参和arguments关系相互独立,各不影响*

3.在对象中不允许有同名的属性

严格模式下:

var obj = {
name:"码农1号",
name:"码农2号"
}
console.log(obj.name);  //打印为:码农2号;相当于执行了obj.name = "码农1号";obj.name = "码农2号";

非严格模式下:

"use strict";
var obj = {
name:"码农1号",
name:"码农2号"
};  //直接报错

二、使用方法

<script>//1  
//在js代码的顶部加上这么一句,声明严格模式的使用
"use strict"; //注意:不能大写
function testFun1 () {
 //此处也为严格模式
}
</script>

<script> //2
//此作用域由于没有声明“严格模式”,因此此作用域的代码按“非严格模式”编译
str = "码农3号"; //不报错
</script>

<script> //3
function testFun2 () {
"use strict";    //只对该函数作用域内的代码有效
}
//此处依然为"非严格模式"
</script>

注意:此处第一组script标签内的代码是使用了“严格模式”,而第二组script标签内的代码不是严格模式。因为每一组script标签就是一个作用域,而“严格模式”的声明只对所在的作用域生效。

11.禁用了八进制

//以0开头的数据为八进制
var num = 023;   
console.log(num);   //输出结果:19

严格模式下:

"use strict";
var num = 023; //显式报错

6.禁用了arguments.callee和caller函数

说明:
arguments.callee 是对函数自身的引用,fun.calller 是对调用函数的引用

//1.arguments.callee指向函数自身,callee常用于递归函数
function testFun() {
  console.log(arguments.callee === testFun);  //true
}
testFun();

//2.caller是对调用自己的函数的引用,以下例子展示了caller的使用
function fun1() {
  //这里可以使用fun1.caller,也可以使用arguments.callee.caller。两者等价
  console.log(arguments.callee.caller);  //这里打印为:fun2(){ fun1(); }
}
function fun2() {
  fun1();
}
fun2();

而在 严格模式 下,这两个方法不能使用,否则程序报错。

7.不能在if语句中声明函数

非严格模式下:

//如果在if语句中声明函数,则会产生语法错误
if (true) {
    function demo() {
        console.log("我是码农");
    }
}
demo(); //打印为:"我是码农";非严格模式下,可以正常调用

严格模式下:

"use strict";
//如果在if语句中声明函数,则会产生语法错误
if (true) {
  function demo() {      //此处报错
    console.log("我是码农");
  }
}

创设eval作用域

正常模式下,Javascript语言有两种变量作用域(scope):全局作用域和函数作用域。严格模式创设了第三种作用域:eval作用域。
正常模式下,eval语句的作用域,取决于它处于全局作用域,还是处于函数作用域。严格模式下,eval语句本身就是一个作用域,不再能够生成全局变量了,它所生成的变量只能用于eval内部。

"use strict";
var x = 2;
console.log(eval("var x = 5; x")); // 5
console.log(x); // 2

9.禁止this指向全局对象

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

var name = "测试的name";
function demoTest() 
    //在非严格模式下,打印出来的this为全局的对象window!在严格模式下打印出来的this为undefined
    console.log(this);  
}
demoTest(); 

四、严格模式使用的注意点(不同点)

对于使用的注意点,本农总结了11点,此文将详细讲解

  1. 所有的变量必须使用var 关键字声明

  2. 不能使用delete关键字删除全局变量 ,以前默认删除失败,严格模式下直接报错

  3. 在对象中不允许有同名的属性

  4. 函数的参数必须唯一(不能出现同名的参数)

  5. arguments对象的行为不同,在非严格模式下修改形参的值会反映到arguments中,而严格模式下则相对独立

  6. 禁用了argument.calleecaller函数,他们一个引用函数本身,一个引用调用函数

  7. 不能在if语句中声明函数

  8. 禁止使用evalarguments作为标识符(变量名)

  9. 禁止this指向全局对象

  10. 禁用了with语句

  11. 去掉了JavaScript中的八进制字面量(以0开头的八进制字面量是无效的语法)

针对以上注意点,下面将讲一一讲解

8.禁止使用eval和arguments作为标识符

//非严格模式下,两者均可被当做 变量名 使用
var eval = "码农1号";
var arguments = "码农2号"
console.log(eval); //输出结果:"码农1号"
console.log(arguments); //输出结果:"码农2号"

//严格模式下,两者不能被当做变量名
"use strict";
var eval = "码农1号";  //直接报错,arguments同理

4.函数的参数必须唯一(不能出现同名的参数)

  • 在非严格模式下,如果函数在定义的时候,使用了多个同名的形参,则在函数内部形参的实际值为最后一个传入的实参值

  • 在严格模式下,直接报错

非严格模式下

function foo(a, b, a) {
console.log(a);
}
foo(1, 2, 3);  //打印为:3

​ 非严格模式下:

"use strict";
function foo(a, b, c) {
console.log(a);
}   //该函数的声明将直接报错

2.不能使用delete关键字删除全局变量

非严格模式下:

//在“非严格模式”下,删除失败(静默失败),失败了不吭声,严格模式下会直接报错
var a = 10;
var result = delete a;  
console.log(result); //打印为:false;删除失败,var声明的变量无法delete关键删除
console.log(a);  //打印为:10

严格模式下:

"use strict";
var a = 10;
var result = delete a;  //这行直接报错

显式报错

一些在正常模式下能正常运行的代码,在严格模式下会显式报错。比如正常模式下,对一个对象的只读属性进行赋值,不会报错,只会默默地失败。严格模式下,将报错。

"use strict";
var obj = {};
//该方法是给对象定义一个属性,并设置它的一些“是否可操作”值
Object.defineProperty(o, "name", { value: "码农1号", writable: false });//将name属性设置为只读
obj.name = "大神"; // 报错  (正常模式下只会默默赋值失败)

本文由分分快三计划发布,转载请注明来源

关键词: 分分快三计划 技术 让前端飞