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游戏开发
JS中的三个部分
ECMAScript(核心)
浏览器端拓展
服务器端拓展
ES的几个重要版本
ES5 : 09年发布
ES6(ES2015) : 15年发布, 也称为ECMA2015
ES7(ES2016) : 16年发布, 也称为ECMA2016 (变化不大)
……
ES5浏览器支持情况
一般来说除了针对个别特性的特殊说明各大主流浏览器都支持es5包括
Chrome 13+
Firefox 4+
Safari 5.1*
IE 9*
注:其中IE9不支持es的严格模式从IE10开始支持。Safari 5.1不支持Function.prototype.bind
在全局 或 函数内部,第一条语句定义为
“use strict”;
注:1. 如果浏览器不支持,只会解析为一条普通的字符串语句,加以忽略,不会有任何副作用
2. 如果这行语句不在第一行,则无效,整个脚本以"正常模式"运行。
在正常模式中,如果一个变量没有声明就赋值,默认是全局变量。严格模式禁止这种用法,全局变量必须显式声明。
a = 100;
//非严格模式下,输出 a: 100
//严格模式下,a没有声明,抛出一个错误 Error: a is not defined
console.log("a:",a);
var num4 = 076;//八进制标识 0
//非严格模式下,使用八进制没有任何位置
//严格模式下,不支持八进制 报错SyntaxError: Octal literals are not allowed in strict mode.
在函数内部,有两个特殊的对象: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);
}
}
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;
(function fn(){
//非严格模式下,普通函数中的this指向window
//严格模式下,普通函数中的this不再指向window 返回undefined
console.log(this);
})();
正常模式下,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
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
正常模式下,如果对象有多个重名属性,最后赋值的那个属性会覆盖前面的值。严格模式下,这属于语法错误**(但是程序目前检测不出来)**
var obj = {a:10,a:100}
正常模式下,如果函数有多个重名的参数,可以用arguments[i]读取。严格模式下,这属于语法错误。
"use strict";
//严格模式下报错 Error: Duplicate parameter name not allowed in this context
function fn(a,a,b){
return;
}
为了向将来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(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 来表示,例如字符串、数字、对象、数组等。但是对象和数组是比较特殊且常用的两种类型。
概述:将内存中的对象转化为字节序列,用于持久化到磁盘中或者通过网络传输。对象序列化的最主要的用处就是传递和保存对象,保证对象的完整性和可传递性。序列化是把对象转换成有序字节流,以便在网络上传输或者保存在本地文件中。序列化后的字节流保存了对象的状态以及相关的描述信息。序列化机制的核心作用就是对象状态的保存与重建。
语法格式:JSON.stringify(obj/arr,callbackfn) 对象的序列化,js对象(数组)转换为json对象(数组)
参数:
obj 必需;要处理的对象
callbackfn 可选;回调函数,函数中有两个参数如下:
第一个参数:属性名
第二个参数:属性值
需求:对象转JSON串的过程中,将 数字字符串 作为 数字保留
概述:从字节序列创建对象的过程称为反序列化。序列化对象和平台无关,序列化得到的字节流可以在任何平台反序列化。从文件中或网络上获得序列化的字节流后,根据字节流中所保存的对象状态及描述信息,通过反序列化重建对象。
语法格式:JSON.parse(json,callbackfn) 对象的反序列化,json对象(数组)转换为js对象(数组)
参数:
str 必需;要处理的json字符串
callbackfn 可选;回调函数,函数中有两个参数如下:
第一个参数:属性名
第二个参数:属性值
需求:JSON串转对象过程中,将 数字字符串 转为 数字
函数 | 描述 |
---|---|
escape() | 对字符串进行编码 |
unescape() | 对由 escape() 编码的字符串进行解码 |
encodeURI() | 把字符串编码为 URI |
decodeURI() | 解码某个编码的 URI |
encodeURIComponent() | 把字符串编码为 URI 组件 |
decodeURIComponent() | 解码一个编码的 URI 组件 |
URI:Uniform Resource Identifiers,通用资源标识符。是一个用于标识某一互联网资源名称的字符串。该种标识允许用户对任何(包括本地和互联网)的资源通过特定的协议进行交互操作。URI由包括确定语法和相关协议的方案所定义。
URL:Uniform Resource Locator,统一资源定位器。它是WWW的统一资源定位标志,就是指网络地址。
URL由三部分组成:资源类型、存放资源的主机域名、资源文件名。也可认为由4部分组成:协议、主机、端口、路径。
格式:protocol / hostname[:port] / path / [;parameters][?query]#fragment ( []为可选项 )
统一资源定位符(Uniform Resource Locator,URL),统一资源名称(Uniform Resource Name,URN)是URI的子集
Web上地址的基本形式是URI,它有两种形式:
- 一种是URL,这是目前URI的最普遍形式。
- 另一种就是URN,这是URL的一种更新形式,URN不依赖于位置,并且有可能减少失效连接的个数。但是其流行还需假以时日,因为它需要更精密软件的支持。
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"