2

严格模式

严格模式的概念

  • 所谓严格模式就是对JavaScript中的一种限制性更强的方式.
  • 属于代码的一种强制规则,来规范代码的格式简单的说就是必须按照严格模式的规则书写代码否则就会报错
  • 严格模式修正了一些引擎难以优化的错误: 同样的代码有些时候严格模式会比非严格模式下更加快

开启严格模式

全局开启严格模式

  • 就是在所有代码之前,定义一个不会赋给任何变量的字符串

示例代码:

// 开启严格模式 - 作用于全局作用域
  'use strict';
// 定义一个变量 - 不使用var关键字

b = '皮卡丘';
console.log(b);

控制台示例图:
图片描述


变量

禁止意外创建变量

  • 没有开启严格模式时

    • 在调用该变量时,不会报错
    • 解释器会自动补全 var关键字
  • 开启严格模式时

    • 在调用该变量时,会报错

示例代码:

// 开启严格模式
'use strict';

var v = '舒克,贝特';
console.log(v);


function fn() {
    /* 在非严格模式:
        * 在函数作用域中定义变量 - 不适用var关键字时JavaScript就会自动将其提升为全局变量
     */
    w = '猫和老鼠';
    console.log(w);
}
fn();
console.log(w);

控制台效果对比图:
图片描述

静默失败转为异常

  • 静默表示既不报错也不显示任何效果
  • 在严格模式下,静默失败会转为报错

示例代码:

// 开启严格模式
'use strict';

const v = 12.19;// 定义常量
v = 1993;// 重新赋值

console.log(v);

控制台效果图:
图片描述

禁用delete关键字

  • 注意: 注意: 严格模式下禁用delete关键字 - 是针对删除变量,而不是数组元素的对象属性的
  • 在非严格模式下,对变量使用delete 会静默失败
  • 在严格模式下,对变量使用delete 会报错

示例代码:

// 开启严格模式
'use strict';

// 注意: 严格模式下禁用delete关键字 - 是针对删除变量,而不是数组元素的对象属性的

// 定义一个全局变量
var v = '皮卡丘';
console.log(v);

delete  v;//删除全局变量v
console.log(v);

//定义一个数组
var arr = [1,2,3,4,5];
delete arr[0];
console.log(arr);


// 定义一个对象
var obj = {
    name : '花花世界'
};
delete obj.name;
console.log(obj.name);

控制台效果对比:
图片描述

对变量名的限制

  • 注意: 严格模式下不允许把保留字当变量名称 - 因为在ES6中保留字会变成关键字

示例代码:

// 开启严格模式
'use strict';

/*
    注意: 严格模式下不允许把保留字当变量名称
      * 因为在ES6中保留字会变成关键字
 */
var static = '一花一世界';
console.log(static);

控制台效果对比图:
图片描述


对象

不可删除的属性

  • 在非严格模式下,使用delete去删除不可删除的属性时,会静默失败

示例代码:

// 开启严格模式
'use strict';

/* 使用delete 删除Object对象的原型属性 */
delete Object.prototype;
/* 在调用Object对象的原型属性 */
console.log(Object.prototype);

控制台效果对比图:
图片描述

属性名必须唯一

  • 当开启严格模式时 - 对象具有相同名称的属性时,编辑器报错(不是运行时报错)
  • 当非严格模式时 - 对象具有相同名称的属性时,后面的会覆盖前面的属性名

示例代码:

// 开启严格模式
 'use strict';

var obj = {
    /*
        当开启严格模式时 - 对象具有相同名称的属性时,编辑器报错(不是运行时报错)
        当非严格模式时 - 对象具有相同名称的属性时,后面的会覆盖前面的属性名
     */
    name : '皮卡丘',
    name : '亚奇洛贝'
};
console.log(obj.name);

控制台效果对比图:
图片描述

只读属性的赋值

  • 在非严格模式下,对只读属性进行从新赋值,会静默失败
  • 在严格模式下,对只读属性进行重新赋值,会报错

示例代码:

// 开启严格模式
'use strict';

/* 定义一个对象 */
var obj = {
    name : '皮卡丘'
};
/* 获取指定属性的属性描述符 - 将属性改为只读属性 */
var result = Object.getOwnPropertyDescriptor(obj,'name');
console.log(result);
// 定义对象obj的只读属性
Object.defineProperty(obj,'age',{
    value : 18
});
// 针对只读属性进行修改操作
// obj.age = 80;
// console.log(obj.age);

delete obj.age;
console.log(obj.age);

控制台效果对比图:
图片描述

不可扩展的对象

  • 在非严格模式下,对不可扩展的对象添加新属性,会静默失败
  • 在严格模式下,对不可扩展的对象添加新属性,会报错

示例代码:

// 开启严格模式
'use strict';

/* 定义一个空对象 */
var obj = {};
// 设置对象obj是一个不可扩展的对象
Object.preventExtensions(obj);
// 为对象obj新增属性
obj.name = '皮卡丘';
/* 调用对象 */
console.log(obj);

控制台效果对比图:
图片描述


函数

参数名必须唯一

  • 在非严格模式下,参数名允许重复,后面匹配的参数会覆盖之前匹配的参数
  • 在严格模式下,参数名重复时,编辑器会提示报错,运行时也会报错

示例代码:

// 开启严格模式
'use strict';

/* 定义一个函数 */
function fn(a,a,b) {
    console.log(a + a + b);
}
/* 调用函数并传递参数 */
fn(1,2,3);

控制台效果对比图:
图片描述

arguments的不同

  • 严格模式下 - arguments对象获取参数的值与形参有关的

    • 如果局部变量与形参名相同 - 就根据就近原则进行获取
  • 严格模式下 - arguments对象获取参数的值与形参无关的

示例代码:

// 开启严格模式
'use strict';

function fn(value) {
    var value = '皮卡丘';
    console.log(value);// 调用结果为 皮卡丘 - 就近原则
    /*
        * 严格模式下 - arguments对象获取参数的值与形参有关的
          * 如果局部变量与形参名相同 - 就根据就近原则进行获取
        * 严格模式下 - arguments对象获取参数的值与形参无关的
     */
    console.log(arguments[0]);// 调用结果为 皮卡丘 , 严格模式下调用结果为 皮皮虾
}
fn('皮皮虾');

控制台效果对比图:
图片描述

arguments对象的callee( )方法

  • 在非严格模式下,callee()方法表示当前调用的函数
  • 在严格模式下,arguments对象将无法调用callee()方法,会报错

示例代码:

// 开启严格模式
'use strict';

/* 定义一个函数 */
function fn() {
    console.log(arguments.length);
    /* 将callee()方法返回 */
    return arguments.callee;
}
fn();

控制台效果对比图:
图片描述

函数声明的限制

  • 在严格模式下, 函数的定义只能在全局作用域与函数作用域(不能再块级作用域定义函数)
  • 在非严格模式下,函数可以在任何作用域下进行定义

示例代码:

// 开启严格模式
'use strict';

// 在全局作用域
function fn() {
    // 在函数作用域
    function n() {}
}
// 在严格模式下, 函数的定义只能在全局作用域与函数作用域(不能再块级作用域定义函数)
for (var i=0; i<10; i++){
    //ECMAScript 6新增 - 存在着块级作用域
    var v = 100;
    function f() {
        console.log('这是一个皮卡丘');
    }
}
console.log(v);
f();

控制台对比效果图:
图片描述


eval()函数

增加eval()作用域

  • 在非严格模式下,eval()函数创建的变量可以在其他位置进行调用
  • 在严格模式下,eval()函数创建的变量只能在当前eval()函数中使用,其他位置调用会报错

示例代码:

// 开启严格模式
'use strict';

// 在严格模式下,增加eval作用域 - eval()函数定义的变量只能在当前eval()函数中使用
eval('var v = "一花一世界";');
// 在全局作用域中调用变量 - 则会报错
console.log(v);// 非严格模式下调用结果为 一花一世界

控制台效果对比图:
图片描述


arguments对象

禁止读写

  • 在非严格模式下,使用 eval 或 arguments 做为标识符(变量名、函数名、对象名)时,会静默失败
  • 在严格模式下,使用 eval 或 arguments 做为标识符(变量名、函数名、对象名)时,会报错

示例代码:

// 开启严格模式
"use strict";

/* 使用 eval 或 arguments 做为标识符 */
eval = 17;
arguments++;
++eval;
var obj = { set p(arguments) { } };
var eval;
try { } catch (arguments) { }
function x(eval) { }
function arguments() { }
var y = function eval() { };
var f = new Function("arguments", "'use strict'; return 17;");

代码效果图:
图片描述


this关键字

抑制this

  • 在非严格模式下,在函数使用apply()方法或call()方法来调用函数时,使用null或undefined来代替this的指向对象时,this会指向全局对象
  • 在严格模式下,在函数使用apply()方法或call()方法来调用函数时,使用null或undefined来代替this的指向对象时,会报错

示例代码:

// 开启严格模式
'use strict';


/* 定义全局变量 */
var v = 100;

/* 定义函数 */
function fn() {
    console.log(this.v);
}


/* 使用appl()方法或call()方法来调用函数 */
fn.call(obj);// this 指向全局对象

控制台效果对比图:
图片描述


a达达
21 声望5 粉丝