【ES5新特性一】 严格模式语法变化、全局的JSON对象、编码和解码的方法

前言

  1. ECMAScript 和 JavaScript 的关系

    一个常见的问题是,ECMAScript 和 JavaScript 到底是什么关系?

    要讲清楚这个问题,需要回顾历史。1996 年 11 月,JavaScript 的创造者 Netscape 公司,决定将 JavaScript 提交给标准化组织 ECMA,希望这种语言能够成为国际标准。次年,ECMA 发布 262 号标准文件(ECMA-262)的第一版,规定了浏览器脚本语言的标准,并将这种语言称为 ECMAScript,这个版本就是 1.0 版。

    该标准从一开始就是针对 JavaScript 语言制定的,但是之所以不叫 JavaScript,有两个原因。一是商标,Java 是 Sun 公司的商标,根据授权协议,只有 Netscape 公司可以合法地使用 JavaScript 这个名字,且 JavaScript 本身也已经被 Netscape 公司注册为商标。二是想体现这门语言的制定者是 ECMA,不是 Netscape,这样有利于保证这门语言的开放性和中立性。

    因此,ECMAScript 和 JavaScript 的关系是,前者是后者的规格,后者是前者的一种实现(另外的 ECMAScript 方言还有 JScript 和 ActionScript)。日常场合,这两个词是可以互换的。

    原生JavaScipt案例合集
    JavaScript +DOM基础
    JavaScript 基础到高级
    Canvas游戏开发

  2. JS中的三个部分

    • ECMAScript(核心)

    • 浏览器端拓展

      • BOM(浏览器对象模型)
      • DOM(文档对象模型)
    • 服务器端拓展

      • Node
  3. ES的几个重要版本

    • ES5 : 09年发布

    • ES6(ES2015) : 15年发布, 也称为ECMA2015

    • ES7(ES2016) : 16年发布, 也称为ECMA2016 (变化不大)

      ……

  4. ES5浏览器支持情况

    一般来说除了针对个别特性的特殊说明各大主流浏览器都支持es5包括

    Chrome 13+

    Firefox 4+

    Safari 5.1*

    IE 9*

    注:其中IE9不支持es的严格模式从IE10开始支持。Safari 5.1不支持Function.prototype.bind

一、严格模式下的语法变化

1.1 基本概述

  • 除了正常的运行模式(混杂模式),ES5中添加了第二种运行模式:“严格模式”(strict mode)
  • 顾名思义,这种模式,使得JavaScript在更严格的语法下运行
  • "严格模式"体现了Javascript更合理、更安全、更严谨的发展方向,包括 IE10 在内的主流浏览器,都已经支持它,许多大项目已经开始全面拥抱它。
  • 另一方面,同样的代码,在"严格模式"中,可能会有不一样的运行结果;一些在"正常模式"下可以运行的语句,在"严格模式"下将不能运行。掌握这些内容,有助于更细致深入地理解Javascript,让你变成一个更好的程序员

1.2 设置严格模式的目的

  • 消除JavaSript语法的一些不合理,不严谨之处,减少一些怪异的行为
  • 消除代码运行的一些不安全之处,为代码的安全运行保驾护航
  • 提高编译器效率,增加运行速度
  • 为未来新版本的JavaScript做好铺垫

1.3 如何使用

在全局 或 函数内部,第一条语句定义为

“use strict”; 

注:1. 如果浏览器不支持,只会解析为一条普通的字符串语句,加以忽略,不会有任何副作用

​ 2. 如果这行语句不在第一行,则无效,整个脚本以"正常模式"运行。

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 对象的函数。但在严格模式下,arguments.callee是被禁止使用的。

如下,实现阶乘的递归调用

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 均不支持严格模式

二、提供全局的JSON对象

2.1 JSON 数据格式概念介绍

  • JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。它基于 ECMAScript(欧洲计算机协会制定的 JS 规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。

  • JSON 键值对是用来保存 JS 对象的一种方式,和 JS 对象的写法也大同小异,键/值对组合中的键名写在前面并用双引号 “” 包裹,使用冒号 : 分隔,然后紧接着值:

    {
    	"pId":"0001",
    	"pName":"花木扶疏",
    	"pAge":"23"
    }
    
  • JSON 与 JS 对象的关系:JSON 是 JS 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串。如

    var obj = {a: 'Hello', b: 'World'}; //这是一个对象,注意键名也是可以使用引号包裹的
    var json = '{"a": "Hello", "b": "World"}'; //这是一个 JSON 字符串,本质是一个字符串
    
  • JSON字符串与对象之间的转换方法:

    JSON.stringfy(obj) 将一个对象转换成字符串形式

    JSON.parse(str) 将一个字符串转换成对象

    var json = JSON.stringify({a: 'Hello', b: 'World'}); //结果是 '{"a": "Hello", "b": "World"}'
    var obj = JSON.parse('{"a": "Hello", "b": "World"}'); //结果是 {a: 'Hello', b: 'World'}
    
  • 在 JS 语言中,一切都是对象。因此,任何支持的类型都可以通过 JSON 来表示,例如字符串、数字、对象、数组等。但是对象和数组是比较特殊且常用的两种类型。

    • 对象:对象在 JS 中是使用花括号包裹 {} 起来的内容,数据结构为 {key1:value1, key2:value2, …} 的键值对结构。在面向对象的语言中,key 为对象的属性,value 为对应的值。键名可以使用整数和字符串来表示。值的类型可以是任意类型。
    • 数组:数组在 JS 中是方括号 [] 包裹起来的内容,数据结构为 [“java”, “javascript”, “vb”, …] 的索引结构。在 JS 中,数组是一种比较特殊的数据类型,它也可以像对象那样使用键值对,但还是索引使用得多。同样,值的类型可以是任意类型。

2.2 序列化和反序列化

2.2.1 序列化
  • 概述:将内存中的对象转化为字节序列,用于持久化到磁盘中或者通过网络传输。对象序列化的最主要的用处就是传递和保存对象,保证对象的完整性和可传递性。序列化是把对象转换成有序字节流,以便在网络上传输或者保存在本地文件中。序列化后的字节流保存了对象的状态以及相关的描述信息。序列化机制的核心作用就是对象状态的保存与重建。

  • 语法格式:JSON.stringify(obj/arr,callbackfn) 对象的序列化,js对象(数组)转换为json对象(数组)

  • 参数

    obj 必需;要处理的对象

​ callbackfn 可选;回调函数,函数中有两个参数如下:

​ 第一个参数:属性名

​ 第二个参数:属性值

需求:对象转JSON串的过程中,将 数字字符串 作为 数字保留

2.2.2 反序列化
  • 概述:从字节序列创建对象的过程称为反序列化。序列化对象和平台无关,序列化得到的字节流可以在任何平台反序列化。从文件中或网络上获得序列化的字节流后,根据字节流中所保存的对象状态及描述信息,通过反序列化重建对象。

  • 语法格式:JSON.parse(json,callbackfn) 对象的反序列化,json对象(数组)转换为js对象(数组)

  • 参数

    str 必需;要处理的json字符串

    callbackfn 可选;回调函数,函数中有两个参数如下:

    ​ 第一个参数:属性名

    ​ 第二个参数:属性值

需求:JSON串转对象过程中,将 数字字符串 转为 数字

2.3 编码和解码的方法

2.3.1 概念
函数描述
escape()对字符串进行编码
unescape()对由 escape() 编码的字符串进行解码
encodeURI()把字符串编码为 URI
decodeURI()解码某个编码的 URI
encodeURIComponent()把字符串编码为 URI 组件
decodeURIComponent()解码一个编码的 URI 组件
  1. URI:Uniform Resource Identifiers,通用资源标识符。是一个用于标识某一互联网资源名称的字符串。该种标识允许用户对任何(包括本地和互联网)的资源通过特定的协议进行交互操作。URI由包括确定语法和相关协议的方案所定义。

  2. URL:Uniform Resource Locator,统一资源定位器。它是WWW的统一资源定位标志,就是指网络地址。

    URL由三部分组成:资源类型、存放资源的主机域名、资源文件名。也可认为由4部分组成:协议、主机、端口、路径。

    格式:protocol 😕/ hostname[:port] / path / [;parameters][?query]#fragment ( []为可选项 )

  3. 统一资源定位符(Uniform Resource Locator,URL),统一资源名称(Uniform Resource Name,URN)是URI的子集

    Web上地址的基本形式是URI,它有两种形式:

    • 一种是URL,这是目前URI的最普遍形式。
    • 另一种就是URN,这是URL的一种更新形式,URN不依赖于位置,并且有可能减少失效连接的个数。但是其流行还需假以时日,因为它需要更精密软件的支持。
2.3.2 方法详述
  • escape()

    escape() 是 js 编码函数中最古老的一个。实际上,escape() 不能直接用于 URL 编码,它的真正作用是返回一个字符的 Unicode 编码值。比如“你好”的返回结果是"%u4F60%u597D"。无论网页的原始编码是什么,一旦被 Javascript 编码,就都变为 unicode 字符。也就是说,Javascipt 函数的输入和输出,默认都是Unicode字符。

    javascript:escape("你好");
    //输出 "%u4F60%u597D"
    解码
    javascript:unescape("%u4F60%u597D");
    //输出 "你好"
    
  • encodeURI()

    encodeURI是对整个URL进行编码,因此除了常见的符号以外,对其他一些在网址中有特殊含义的符号“; / ? : @ & = + $ , #”,也不进行编码。编码后,它输出符号的utf-8形式,并且在每个字节前加上%,需要注意的是,它不对单引号’编码。

    encodeURI("https://mp.csdn.net?=k=hello world");
    //输出 "https://mp.csdn.net?=k=hello%20world"
    

    它对应的解码函数是decodeURI()

    decodeURI("https%3A//mp.csdn.net/mdeditor%23Markdown_2");
    //输出 "https://mp.csdn.net?=k=hello world"
    
  • encodeURIComponent()

    与encodeURI()的区别是,它用于对URL的组成部分进行个别编码,而不用于对整个URL进行编码。因此,“; / ? : @ & = + $ , #”,这些在encodeURI()中不被编码的符号,在encodeURIComponent()中统统会被编码,所以encodeURIComponent()相比encodeURI()要更加彻底。至于具体的编码方法,两者是一样。

    encodeURIComponent("https://mp.csdn.net?=k=hello world");
    //输出 "https%3A%2F%2Fmp.csdn.net%3F%3Dk%3Dhello%20world"
    

    它对应的解码函数是decodeURIComponent()

    decodeURIComponent("https%3A%2F%2Fmp.csdn.net%3F%3Dk%3Dhello%20world");
    //输出 "https://mp.csdn.net?=k=hello world"
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MagnumHou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值