JS面向对象中的严格模式

严格模式

严格模式是什么

严格模式是JavaScript中的一种限制性更强的变种方式。严格模式不是一个子集:它的语义上与正常代码有着明显的差异。

不支持严格模式的浏览器与支持严格模式的浏览器行为上也不一样,所以在未经严格模式特性测试情况下使用严格模式。

严格模式可以与严格模式共存,所以脚本可以逐渐的选择性加入严格模式。

严格模式的目的

首先,严格模式会将JavaScript陷阱直接变成明显的错误。

其次,严格模式修正了一些引擎难以优化的错误;同样的代码有些时候严格模式会比严格模式下更快

第三,严格模式禁用了一些有能在未来版本中定义的语法。

开启严格模式

全局开启严格模式

在JavaScript中想要开启严格模式,需要在所有代码之前,定义一个不会赋给任何变量的字符串

"use strict";//或者'use strict'
函数开启严格模式

也可以为某个指定的函数开启严格模式,

//函数外依旧是非严格模式
function doSomething(){
	"use strict";//开启严格模式
	//其他代码
}

在匿名函数中使用严格模式,相当于在全局开启严格模式的变通事项方式。

(function(){
	"use strict";//开启严格模式
})();

代码:

// 开启严格模式 - 作用于全局作用域
// "use strict"
// 定义一个变量 - 不使用var关键字
a = 100;
console.log(a);

function fn(){
    // 开启严格模式 - 作用于函数作用域
    "use strict"
    v = 200;
    console.log(v);
}
fn();

效果:
在这里插入图片描述

变量

禁止意外创建变量

在严格模式下,不允许意外创建全局变量

  • 如下代码是非严格模式下意外创建全局变量

    //未声明变量
    message = "this is message"
    
  • 如下代码是严格模式下意外创建全局变量

    "use strict";//开启严格模式
    
    //严格模式下,意外创建全局变量,抛出ReferenceError
    
// 开启严格模式
"use strict";

v = 100;
console.log(v);

function fn(){
    // 在非严格模式:在函数作用域中定义变量 - 不使用var关键字 -> 自动将其提升为全局变量
    w = 200;
    console.log(w);
}
fn();
console.log(w);

效果:
在这里插入图片描述

  • 开启严格模式后,定义变量要带var,否则会报错
静默失败转为异常

所谓静默失败就是既不报错也没有任何效果,例如改变常量的值 。在严格模式下,静默失败会转换成抛出异常。

  • 如下代码是非严格模式下的静默失败。

    const PI = 3.14;
    PI = 1.14//静默失败
    console.log(PI);//3.14
    
  • 如下代码是严格模式下的静默失败。

    "use strict";//开启严格模式
    
    const PI = 3.14;
    PI = 3.14//抛出TypeError错误
    

代码:

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

const v = 3.14;// 定义常量
v = 1.14;// 重新赋值

console.log(v);

效果:
在这里插入图片描述

禁用delete关键字

在严格模式下,不能对变量使用delete运算符。

  • 如下代码是非严格模式下使用delete运算符,结果会静默失败

    var color = "red";
    delete color
    
  • 如下代码是严格模式下使用delete运算符,结果会抛出异常。

    "use strict";//开启严格模式
    
    var color = "red";
    delete color;//抛出ReferenceError错误
    

    代码:

    // 开启严格模式
    "use strict";
    // 严格模式下禁用delete关键字 -> 针对删除变量,而不是数组元素和对象属性
    
    // var v = 100;// 定义一个全局变量
    // console.log(v);
    //
    // delete v;// 删除全局变量v
    // console.log(v);// undefined
    
    // var arr = [1,2,3,4,5];
    // delete arr[0];
    // console.log(arr);
    
    var obj = {
        name : '肖德硕'
    }
    delete obj.name;
    console.log(obj.name);
    
对变量名的限制

在严格模式下,JavaScript对变量名的限制。特别不能使用如下内容作为变量名:
在这里插入图片描述

上述内容都是保留字,在ECMAScript的下一个版本中可能会用到他们。

在严格模式下,使用上述标识符作为变量名会导致语法错误

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

var static = 100;
console.log(static);//SyntaxError: Unexpected strict mode reserved word

对象

不可删除属性

在严格模式下,不能使用delete运算符删除不可删除的属性。

  • 如下代码是非严格模式下使用delete运算符删除不可删除的属性,结果会静默失败。

    delete Object.prototype
    
  • 如下代码是严格模式下使用delete运算符删除不可删除的属性,结果会抛出异常

    "use strict";//开启严格模式
    
    delete Object.prototype;//抛出TypeError错误
    

代码:

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

// delete Object.prototype;
// console.log(Object.prototype);

delete Math.random;
console.log(Math.random);
// Math.random();
属性名必须唯一

在严格模式下,一个对象内的所有属性名在对象内必须唯一。

  • 如下代码是非严格模式下重名是允许的,最后一个重名的属性决定其属性值。

    var o = {
    	p : 1,
    	p : 2
    };
    
  • 如下代码是严格模式下重名属性被认为是语法错误

    "use strict";//开启严格模式
    
    var o = {
    	p : 1,
    	p : 2
    };
    

代码:

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

// 对象具有相同名称的属性时 - 编辑器报错(不是运行时报错)
var obj = {
    name : '肖德硕',
    name : '小肖'
}
console.log(obj.name);

效果:
在这里插入图片描述

只读属性的赋值

在严格模式下,不能为一个只读的属性进行重新赋值。

  • 如下代码是非严格模式为只读属性重新赋值,结果会静默失败。

    var obj1 = {};
    
    Object.defineProperty(obj1,"x",{
    	value : 42,
    	writable : false
    });//将属性设置为只读
    obj1.x = 9;
    
  • 如下代码是严格模式下为只读属性重新赋值,结果会抛出异常

    "use strict";//开启严格模式
    
    var obj1 = {};
    
    Object.defineProperty(obj1,"x",{
    	value : 42,
    	writable : false
    });//将属性设置为只读
    obj1.x = 9;//抛出TypeError错误
    

代码:

// 开启严格模式
"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);

效果:
在这里插入图片描述

不可扩展的对象

在严格模式下,不能为不可扩展的对象添加新属性。

  • 如下代码是非严格模式为不可扩展的对象添加新属性,结果会静默失败。

    var obj = {};
    Object.preventExtensions(obj);//将对象变的不可扩展
    obj.newProp = 'ohai';
    
  • 如下代码是严格模式不可扩展的对象添加新属性,结果会抛出异常。

    "use strict";//开启严格模式
    
    var obj = {};
    Object.preventExtensions(obj);//将对象变的不可扩展
    obj.newProp = 'ohai';//抛出TypeError错误
    

代码:

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

var obj = {};
// 设置对象obj是一个不可扩展的对象
Object.preventExtensions(obj);
// 为对象obj新增属性
obj.name = '肖德硕';
console.log(obj);

效果:
在这里插入图片描述

函数

参数名必须唯一

在严格模式下,要求命名函数的参数必须唯一。

  • 如下代码是非严格模式下最后一个重名参数会掩盖之前的重名参数,之前的参数仍然可以通过arguments[i]来访问

    function sun(a,a,c){}
    
  • 如下代码是严格模式下重名参数被认为是语法错误。

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

代码:

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

function fn(a, a, b){
    console.log(a + a + b);
}
fn(1,2,3);

效果;
在这里插入图片描述

arguments的不同

在严格模式下,arguments对象的行为也有所不同。

  • 非严格模式下,修改命名参数的值也会反应到arguments对象中。
  • 严格模式下,命名参数与arguments对象是完全独立的。
// 开启严格模式
"use strict";

function fn(value){
    var value = '肖德硕';
    console.log(value);// 肖德硕 -> 就近原则
    /*
         非严格模式下 - arguments对象获取参数的值与形参有关的
           如果局部变量与形参名相同 - 根据就近原则进行获取
         严格模式下 - arguments对象获取参数的值与形参无关的
     */
    console.log(arguments[0]);// 非严格模式 -> 肖德硕   严格模式 -> 小肖
}
fn('小肖');

效果:
在这里插入图片描述

arguments对象的callee()方法

在严格模式下,不能使用arguments对象的callee()方法。

  • 如下代码是非严格模式下使用arguments对象的callee()方法,表示调用函数本身。

    var f = function(){
    	return arguments.callee;
    };
    f();
    
  • 如下代码是严格模式下使用arguments对象的callee()方法,结果会抛出异常。

    "use strict";//开启严格模式
    
    var f = function(){
    	return arguments.callee;
    };
    f();//抛出TypeError错误
    

代码:

// 开启严格模式
"use strict";
// 在严格模式下,arguments对象无法调用callee()方法
function fn(){
    console.log(arguments.length);
    // return arguments.callee;//TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
}
fn();
函数声明的限制

在严格模式下,只能在全局域和函数域中声明函数。

  • 如下代码是非严格模式下在任何位置声明函数都是合法的

    if(true){
    	function f(){}
    }
    
  • 如下代码是严格模式下在除全局域和函数域中声明函数是语法错误。

    "use strict";//开启严格模式
    
    if(true){
    	function f(){}//!!!语法错误
    }
    

代码:

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

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

效果:
在这里插入图片描述

增加eval作用域

在严格模式下,使用eval()函数创建的变量只能在eval()函数内部使用。

  • 如下代码是非严格模式下eval()函数创建的变量在其他位置可以使用。

    eval("var x = 42");
    console.log(x);//42
    
  • 如下代码是严格模式下eval()函数创建的变量只能在eval()函数内部使用。

    "use strict";//开启严格模式
    
    eval("var x = 42");
    console.log(x);//抛出ReferenceError错误
    

代码:

// 开启严格模式
"use strict";
// 在严格模式下,增加eval作用域 - eval()函数定义的变量只能在当前eval()函数中使用
eval('var v = 100;');
// 在全局作用域中调用变量 - 报错
console.log(v);// 100

效果:
在这里插入图片描述

arguments和eval禁止作为标识

禁止读写

在严格模式下,arguments和eval()禁止作为标识符,也不允许读写他们的值

  • 使用var声明
  • 赋予另一个值
  • 尝试修改包含的值
  • 用作函数名
  • 用作命名的函数的参数
  • 在try……catch语句中用作例外名

在严格模式下,一下所有尝试将导致语法错误:

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

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

  • 在非严格模式下使用函数的apply()或call()方法时,null或undefined值会被转换为全局对象
  • 在严格模式下,函数的this值始终是指定的值(无论什么值)。
// 开启严格模式
"use strict";

var v = 100;

function fn(){
    console.log(this.v);
}

var obj = {
    v : 200
}

fn.call(obj);// this指向全局对象
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值