概述
ECMAScript 5.1就是我们常说的es5。它在2012年就已经被公开。时至今日,除了一些较低版本的浏览器,各大主流浏览器都已经实现支持了es5的绝大部分特性。
数字化管理平台
Vue3+Vite+VueRouter+Pinia+Axios+ElementPlus
Vue权限系统案例
个人博客地址
先上一段代码,体会一下:
<body> <h2>单项数据绑定:通过修改JS中的数据,页面呈现最新修改的数据信息。这是一种映射关系,把JS数据的变化映射到DOM结构上</h2> <div id="box">数据单项绑定呈现位置</div> <input type="text" id="ipt"> </body> <script src="./js/jquery-1.12.3.min.js"></script> <script> // 创建对象 // var obj = { // des:"把Model的变化映射到DOM结构上" // } // 获取元素 // var box = document.getElementById("box"); // // 设置元素的内部文本 // box.innerHTML = obj.des; // 普通的方式,修改对象的值,查看页面DOM数据变化 // obj.des = "新的数据";//页面不会发生改变,除非通过innerHTML重新写入 // 通过set方法设置单项绑定 // Object.defineProperty(obj,'des',{ // //赋值器 // set:function(value){ // // 当设置或修改新的值时,将最新的值输出到页面 // box.innerHTML = value; // // 备用属性赋值 // this.oDes = value; // }, // // 取值器 // get:function(){ // return this.oDes; // } // }); // 再次修改以下值试试 // obj.des = "新的值";//发现页面内容更新了 // 现在我们做这样一个修改,页面添加一个输入框,随着输入框内容的输入,上面呈现输入框中的内容,修改如下: // 创建对象 var obj = { des:"把Model的变化映射到DOM结构上" } // 获取元素 var box = document.getElementById("box"); var ipt = document.getElementById("ipt"); // 设置元素的内部文本 box.innerHTML = obj.des; Object.defineProperty(obj,'des',{ //赋值器 set:function(value){ // 当设置或修改新的值时,将最新的值输出到页面 box.innerHTML = value; // 备用属性赋值 this.oDes = value; }, // 取值器 get:function(){ return this.oDes; } }); // 新的值来自于页面输入框 触发正在输入事件 // ipt.oninput = function(){ // if(this.value === ""){ // box.innerHTML = "把Model的变化映射到DOM结构上"; // }else{ // obj.des = this.value; // } // } // 含有输入法时,不能检测中文,改造并使用jQuery(使用js也可)如下: /** * 拓展:实现中文输入法下,仅在选词后触发input事件 * 描述:在使用oninput监控输入框内容变化时,我们期望仅在value值变化时,才触发oninput事件,而在中文输入下,未选词时的按键也会触发oninput事件。 * 两个事件: * compositionstart事件 * compositionend事件 * 实现方式:使用一个变量表示拼写状态,在oninput事件中判断是否在拼写状态,当拼写状态结束,继续执行下一步操作。 * 代码示例如下: **/ // 定义是否开启输入法的开关 默认关闭 var flag = false; //oninput在oncompositionend之前执行,需加定时器 ipt.oninput = function(){ this.addEventListener('compositionstart',function(){//中文开始书写 flag = true;//检测到中文输入法开启,设为true }) this.addEventListener('compositionend',function(){//中文书写完毕,选取文字完毕 flag = false;//输入完毕,设置false }) setTimeout(function() { if(!flag) {//保证输入法没有开启也能正常获取数据 if(ipt.value === ""){ box.innerHTML = "把Model的变化映射到DOM结构上"; }else{ obj.des = ipt.value; } } },0); } </script>
一、严格模式
1.1 基本概述
除了正常的运行模式(混杂模式),ES5中添加了第二种运行模式:“严格模式”(strict mode)
顾名思义,这种模式,使得JavaScript在更严格的语法下运行
"严格模式"体现了Javascript更合理、更安全、更严谨的发展方向,包括IE 10在内的主流浏览器,都已经支持它,许多大项目已经开始全面拥抱它。
另一方面,同样的代码,在"严格模式"中,可能会有不一样的运行结果;一些在"正常模式"下可以运行的语句,在"严格模式"下将不能运行。掌握这些内容,有助于更细致深入地理解Javascript,让你变成一个更好的程序员
1.2 设置严格模式的目的
消除JavaSript语法的一些不合理,不严谨之处,减少一些怪异的行为
消除代码运行的一些不安全之处,为代码的安全运行保驾护航
提高编译器效率,增加运行速度
为未来新版本的JavaScript做好铺垫
1.3 如何使用
在全局 或 函数内部,第一条语句定义为
“use strict”;
如果浏览器不支持,只会解析为一条普通的字符串语句,加以忽略,不会有任何副作用
如果这行语句不在第一行,则无效,整个脚本以"正常模式"运行。
1.4 语法和行为改变
1.4.1 必须使用var声明变量
在正常模式中,如果一个变量没有声明就赋值,默认是全局变量。严格模式禁止这种用法,全局变量必须显式声明。
a = 100; //非严格模式下,输出 a: 100 //严格模式下,a没有声明,抛出一个错误 Error: a is not defined console.log("a:",a);
1.4.2 禁止使用八进制数
var num4 = 076;//八进制标识 0 //非严格模式下,使用八进制没有任何位置 //严格模式下,不支持八进制 报错SyntaxError: Octal literals are not allowed in strict mode.
1.4.3 禁止使用arguments.callee
在函数内部,有两个特殊的对象:arguments 和 this。其中, arguments 的主要用途是保存函数参数,但这个对象还有一个名叫 callee 的属性,该属性是一个指针,指向拥有这个 arguments 对象的函数。
但在严格模式下,是被禁止使用的。
如下,实现阶乘的递归调用
function factorial(num){ if(num == 1){ return 1; }else{ // return num * factorial(num - 1);//原来阶乘方式 //非严格模式下,使用arguments.callee()指向拥有这个arguments对象的函数 //严格模式下禁止使用 报错TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them return num * arguments.callee(num - 1); } }
1.4.4 禁止使用 delete 删除变量
delete常用于删除对象中的属性;如果使用delete删除一个变量,在正常模式下可以执行通过,但不会删除成功;在严格模式下是禁止这样使用的
// 定义变量a var a = 100; // 定义window全局对象的变量b window.b = 200; // 以上两个都属于全局变量 // 删除操作 // 非严格模式下,可以删除window对象的全局变量b,但是不能删除使用var声明的全局变量a,不会报错 // 严格模式下,禁止使用delete删除变量,一旦使用就会报错:SyntaxError: Delete of an unqualified identifier in strict mode delete a; delete b;
1.4.5 禁止自定义函数中的this指向window
(function fn(){ //非严格模式下,普通函数中的this指向window //严格模式下,普通函数中的this不再指向window 返回undefined console.log(this); })();
1.4.6 创建 eval 作用域,即:块级作用域
正常模式下,Javascript语言有两种变量作用域(scope):全局作用域和函数作用域。严格模式创设了第三种作用域:eval作用域。
正常模式下,eval语句的作用域,取决于它处于全局作用域,还是处于函数作用域。严格模式下,eval语句本身就是一个作用域,不再能够生成全局变量了,它所生成的变量只能用于eval内部使用
eval("var x = 10;"); // 非严格模式下,x为10 // 严格模式下,x没有声明,抛出一个错误 Error: s is not defined alert(x); 任意由eval()创建的变量或函数仍呆在eval()里。然而,你可以通过从eval()中返回一个值的方式实现值的传递: var result = eval("var a = 10,b = 20;a + b"); // 严格模式与非严格模式下都能正常工作(得到30) console.log("result:",result);//result: 30
1.4.7 width作用域
with(target){}方法:
正常模式下:如果添加了tatget对象,它会把这个对象,当作with要执行的代码体的作用域的最顶端,也就是with会改变作用域链。
作用域链是经过很复杂的情况生成的结构,作用域链改了之后,系统内核会消耗大量的效率去更改作用域链,是会把程序变得非常慢的。
所以,在ES5严格模式下,with方法就不可以再使用了。
"use strict"; var num = 10; var obj = { name:"张三", num:100 } fn() function fn(){ var num = 1000; // console.log(num);//1000 // with(window){ // console.log(num);//10 // } with(obj){ console.log(num);//100 var score = 99; console.log(score);//99 } console.log(score);//99 } // console.log(score);//Error: score is not defined width(){}中声明的不存在的变量的作用域由它所在的那个作用域决定 // 严格模式下不支持 width(){} 报错 SyntaxError: Strict mode code may not include a with statement
1.4.8 对象不能有重名的属性
正常模式下,如果对象有多个重名属性,最后赋值的那个属性会覆盖前面的值。严格模式下,这属于语法错误(但是程序目前检测不出来)。
var obj = {a:10,a:100}
1.4.9 函数不能有重名的参数
正常模式下,如果函数有多个重名的参数,可以用arguments[i]读取。严格模式下,这属于语法错误。
"use strict"; //严格模式下报错 Error: Duplicate parameter name not allowed in this context function fn(a,a,b){ return; }
1.4.10 保留字
为了向将来Javascript的新版本过渡,严格模式新增了一些保留字:implements, interface, let, package, private, protected, public, static, yield。
使用这些词作为变量名将会报错。
//非严格模式下不会报错 //严格模式下报错 Error: Unexpected strict mode reserved word var let = 10;
此外,ECMAscript第五版本身还规定了另一些保留字(class, enum, export, extends, import, super),以及各大浏览器自行增加的const保留字,也是不能作为变量名的。
注意:经过测试 IE6,7,8,9 均不支持严格模式