【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"
    

你可能感兴趣的:(前端开发,JavaScript,javascript,ES5,JSON,编码,解码)