JavaScript中的严格模式

最近在看周爱民老师出版的JavaScript语言精髓与编程实践第三版,让我重新认识了js的严格模式,今天就分享一下我的学习笔记

### 简介

JavaScript从ES5开始支持严格模式,需要使用字符串序列来开启:“use strict”;

在代码中他是一个字符串字面量,被用在一段代码文本的最前面,作为“指示前缀”

由于JavaScript中的代码块是按语句来解析的,因此在"use strict"后面加上分号或回车符就可以将该指示前缀解释成“字面量表达式语句”,从而开启相应代码块中的严格模式

### 开启严格模式的两种方式

#### 1、显式声明开启

###### 1、在全局代码的开始处加入

###### 2、在eval代码开始处加入

###### 3、在函数声明代码开始处加入

###### 4、在new Function()所传入的body参数块开始处加入

####2、默认开启

###### 1、模块中

###### 2、类声明和类表达式的整个声明块中

###### 3、在引擎或宿主的运行参数中指定,如:“node --use_strict”

### 严格模式下的限制

#### 语法限制

语法限制是指如果代码文本中出现了违例,则在语法分析期该代码文本就是无效的,其所在的代码块完全不能装载执行(提示语法错误异常)

##### 严格模式下导致语法错误异常的情况

###### 1、在对象字面量声明中存在相同的属性名

```javascript

// 严格模式下会报语法错误

var obj = {

  name: 'kim',

  name: 'xie',

}

```

###### 2、在函数声明中,参数表中带有相同的参数名

```javascript

// 严格模式下会报语法错误

function fn(x,x,y,z,y){

return x + y;

}

// 非严格模式下,访问同名的参数时,只有最后一个声明时有效的

fn(1,2,3,4,5) => return 7

fn(1,2) => return NaN

```

###### 3、不能声明或重写eval和arguments这两个标识符

```javascript

// 严格模式下会报语法错误

// 1、向eval和arguments赋值

eval = function(){}

// 2、向eval和arguments重新声明

var arguments;

// 3、将eval和arguments用作catch子句的异常对象名

try{

// ...

}catch(eval){

// ...

}

// 4、将eval或arguments用作函数名

function arguments(){

// ...

}

// 5、删除arguments或形参名

function fn(){

delete arguments;

}

```

###### 4、用0前缀声明的八进制字面量

```javascript

// 严格模式下会报语法错误

var num = 012;

console.log(num);

// 非严格模式下打印 10

```

###### 5、用delete删除显式声明的标识符、名称或具名函数

```javascript

// 严格模式下会报语法错误

// 删除变量

var x;

delete x;

// 删除具名函数

function fn(){};

delete fn;

// 删除函数形参

function fn(x){

delete x;

}

// 删除catch子句声明的异常对象

try {

// ...

}catch (e){

delete e;

}

// 非严格模式下,这些操作默认是“无效的”,不会抛出异常

// 如果delete删除其他一些不能被删除的对象属性、标识符时将导致执行期异常

```

###### 6、在代码中使用一些扩展的保留字,保留字包括:implements、interface、let、package、private、protected、public、static以及yield

```javascript

// 严格模式下会报语法错误

var yield;

function let(){}

```

###### 7、在代码中包括with语句

```javascript

// 严格模式下会报语法错误

function(){

with(arguments) return length;

}

// 严格模式下with语句直接被禁止了

```

#### 执行限制

执行限制是指将会导致运行期错误的限制

##### 严格模式下导致运行期异常的情况

###### 1、向不存在的标识符赋值将导致“引用异常”

```javascript

// 严格模式下会报执行异常

// 向不存在的标识符赋值

a = '123';

// 由于js中允许局部变量访问上级作用域链的变量

// 所以在语法分析阶段并不能确认a是否真实存在执行环境中

// 正确的做法是,显式声明,或确保外层作用域存在这个变量名

"use strict";

var a = '123';

function fn(){

a="1";

}

```

###### 2、运算符处理一些不可处理的操作数时将导致“类型异常或语法错误”

```javascript

// 严格模式下会报执行异常

var obj = {

x: 100

}

// 1、当对象是不可扩展时,向不存在的属性赋值

Object.preventExtensions(obj);

obj.y = 10;

// 2、当对象是不可删除的属性(isSealed或isFrozen为真时),尝试删除属性

Object.seal(obj);

delete obj.x;

// 3、删除某些不能删除的系统属性、标识符,或configurable性质为false的属性

delete Function.prototype;

// 4、写只读属性

Object.defineProperty(obj, 'x', {writable: false});

obj.x = 200;

// 5、写常量

const a = '123';

a = 'q';

// 上述对属性的操作中,由于属性的性质时可以在运行期改变的

// 因此在语法分析并不能确认上述操作是否有效

```

###### 3、访问arguments.callee或函数的caller属性将导致“类型异常”

```javascript

// 严格模式下会报执行异常

function fn(){

  console.log(typeof arguments.callee)

  console.log(typeof arguments.callee.caller)

  console.log(typeof fn.caller)

}

// 这里的异常时由属性存取运算符导致的,严格模式下运算符认为callee\caller是不正确的

function fn2(){

  console.log('caller' in fn2); //  => true

  console.log('callee' in arguments); //  => true

}

```

###### 4、以下代码的执行效果与非严格模式并不一致

```javascript

// 严格模式下会报执行异常

// 对arguments[n]与形式的修改将不再相互影响

// 在严格模式中返回传入的x的值

// 在非严格模式下返回100

function fn(x){

arguments[0] = 100;

  return x;

}

```

### 严格模式限制的范围

除非在创建和启动js引擎时将它置为严格模式,或者通过模块来加载整个系统,否则默认情况下用户代码只能指定一个有限范围的严格模式

#### 有限范围下的严格模式

###### 1、如果一段代码被标志为“严格模式”,则其中运行的所有代码都必然是严格模式下的(类似于全局作用域)

###### 2、如果在某个函数内部加入严格模式,它不会影响到外面的代码(类似局部作用域)

###### 3、如果“指示前缀”出现在代码中间,作为一个字面量表达式语句时,那么它将会被忽略,也不会导致代码块进入严格模式

#### 严格模式下动态执行非严格模式的全局环境

在任何处于严格模式的代码中,js引擎都允许用户代码通过以下两种方式将代码执行在一个非严格模式的全局环境中

###### 1、使用间接调用的eval()函数

###### 2、使用new Function方式创建的函数

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,133评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,682评论 3 390
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,784评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,508评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,603评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,607评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,604评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,359评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,805评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,121评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,280评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,959评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,588评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,206评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,193评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,144评论 2 352