优秀的编程知识分享平台

网站首页 > 技术文章 正文

ECMAScript和JavaScript有啥区别?

nanyue 2024-10-23 12:10:43 技术文章 2 ℃

简单理解:

ECMAScript是一个标准,

JavaScript是一个实现 。

1、ECMAScript的简介

ECMAScript是一种由Ecma国际(前身为欧洲计算机制造商协会,英文名称是European Computer Manufacturers Association)通过ECMA-262标准化的脚本程序设计语言。这种语言在万维网上应用广泛,它往往被称为JavaScript或JScript,所以它可以理解为是JavaScript的一个标准,但实际上后两者是ECMA-262标准的实现和扩展。

2、JavaScript的简介

JavaScript一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在HTML(标准通用标记语言下的一个应用)网页上使用,用来给HTML网页增加动态功能。

JavaScript是通用的跨平台脚本语言,遵守ECMA-262标准(ES标准),换句话说就是ECMAScript的方言。为了取得技术优势,微软推出了JScript,CEnvi推出ScriptEase,与JavaScript同样可在浏览器上运行。为了统一规格,因为JavaScript兼容于ECMA标准,因此也称为ECMAScript。

JavasSript商标属于Oracle公司,因为Sun公司被Oracle收购。JavaScript早年被Sun公司注册,代表JavaScript这门语言。但是最早发明JavaScript是网景公司。在1995年时,由Netscape公司的Brendan Eich,在网景导航者浏览器上首次设计实现而成。因为Netscape与Sun合作,Netscape管理层希望它外观看起来像Java,因此取名为JavaScript。但实际上它的语法风格与Self及Scheme较为接近。

3、ES6:全称ECMAScript 6.0

ES6经过持续几年的磨砺,它已成为 JS 有史以来最实质的升级,特性涵盖范围甚广, 小到受欢迎的语法糖,例如箭头函数(arrow functions)和简单的字符串插值(string interpolation),大到烧脑的新概念,例如代理(proxies)和生成器(generators);它将彻底改变程序员们编写JS代码的方式。

ES6兼容性列表:http://kangax.github.io/compat-table/es6/

3.1、新语法

let关键字

let a;
let b, c, d;
let e = 1;
let f = 1, g= "hello";
  • 不允许重复声明;
  • 块级作用域(只在代码块内生效 {});
  • 不存在变量提升;
  • 不影响作用域链;

const定义常量

const MAX_AGE = 100;
  • 一定要赋予初始值。
  • 一般常量使用大写(潜规则),一些函数定义的其他情况除外。
  • 常量值不允许修改。
  • 块级作用域。
  • 对数组和对象的元素修改,不算对常量的修改,不会报错。

变量的解构赋值

//数组的解构
const TEST01=[1,2,3,4];
let [a, b, c, d]=TEST01;

//对象的解构
const TEST02={name:"zhangsan", age:10,say:function(){}};
let {name, age, say} = TEST02;
  • 按照一定的模式,从数组或者对象中获取值,并对对象赋值的过程,称为解构。

模板字符串

//字符串赋值方式有:"",''
//ES6新增:``
let name="张三";
let str=`你好,${name}`;
  • 内容中可以直接出现换行符。
  • 直接变量拼接:${var}。

简化对象写法

let name = "张三";
let say = function(){};

//简化写法
let zhangsan = {
    name,
    say
};
//等效于
let zhangsan = {
    name: name,
    say: say
};

//方法声明简化
let test = {
    say(){
        console.log("你好");
    }
};
//等效于
let test = {
    say: function(){
        console.log("你好");
    }
};
  • 允许大括号内直接写变量和函数,作为对象的属性和方法。

箭头函数

//声明方式:=>定义函数
let add = (a, b)=>{
    return a+b;
}
  • this是静态的,this始终指向函数声明时所在作用域下的this。
  • 不能作为构造函数实例化对象。
  • 不能使用arguments变量。
  • 箭头函数的简写:省略小括号:形参有且只有一个;省略花括号,当代码只有一条语句的时候, 此时return也要省略,语句的返回结果就是函数的返回结果。
  • 适用于this无关的回调操作,不适用于this有关的回调。

函数参数默认值

//ES6允许函数参数赋值默认值
function add(a,b=10){
    return a+b;
}
  • 具有默认值的参数一般要放到最后。
  • 可与解构赋值结合:function add({a, b, c})。

rest参数:可变参数

// ...表示
function(...args){
    console.log(args);//数组
}
  • rest参数必须最后。

扩展运算符

//[...]扩展运算符:将数组转换为逗号分割的参数序列。
let a =[1,2,3];
function say(){
    console.log(arguments);
}
say(...a);//实参位置,相当于:say(1,2,3);
  • 应用:数组合并:[...a,...b];数组的克隆:let b = [...a];将伪数组转化为真正数组:dom:Object-Array。

Symbol原始数据类型

let s = Symbol();

let s1 = Symbol("你好");
let s2 = Symbol("你好");
//s1===s2:false

let s3 = Symbol.for("你好");
let s4 = Symbol.for("你好");
//s3===s4:true

//使用
let person ={
    name:"张三",
    say:function(){
    }
};
let methods={
    say:Symbol("say")
};
person[methods.say]=function(){  
};
//这样就可以预防新增加方法影响原有的方法。
  • 表示独一无二的值。
  • 第七种数据类型:Number,String,Boolean,Undefined,Null,Object,Symbol
  • 类似于字符串的数据类型。
  • 特征:值唯一,解决命名冲突问题。不能与其他数据进行运算。对象属性不能通过for in循环遍历,但是可以通过Reflect.ownKeys来获取所有的键名称。
  • 使用场景:给对象添加对于无二的属性,方法。
  • 内置值(11个):
    Symbol.hasInstance: 对象的Symbol.hasInstance属性,指向一个内部方法。当其他对象使用instanceof运算符,判断是否为该对象的实例时,会调用这个方法。比如,foo instanceof Foo在语言内部,实际调用的是Foo[Symbol.hasInstance](foo)。
    Symbol.isConcatSpreadable: 对象的Symbol.isConcatSpreadable属性等于一个布尔值,表示该对象用于Array.prototype.concat()时,是否可以展开。
    Symbol.species: 对象的Symbol.species属性,指向一个构造函数。创建造衍生对象时,会使用该属性。
    Symbol.match:对象的Symbol.match属性,指向一个函数。当执行str.match(myObject)时,如果该属性存在,会调用它,返回该方法的返回值。
    Symbol.replace:对象的Symbol.replace属性,指向一个方法,当该对象被String.prototype.replace方法调用时,会返回该方法的返回值。
    Symbol.search:对象的Symbol.search属性,指向一个方法,当该对象被String.prototype.search方法调用时,会返回该方法的返回值。
    Symbol.split:对象的Symbol.split属性,指向一个方法,当该对象被String.prototype.split方法调用时,会返回该方法的返回值。
    Symbol.iterator: 对象的Symbol.iterator属性,指向该对象的默认遍历器方法。Symbol.toPrimitive:对象的Symbol.toPrimitive属性,指向一个方法。该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。
    Symbol.toStringTag:对象的Symbol.toStringTag属性,指向一个方法。在该对象上面调用Object.prototype.toString方法时,如果这个属性存在,它的返回值会出现在toString方法返回的字符串之中,表示对象的类型。也就是说,这个属性可以用来定制[object Object]或[object Array]中object后面的那个字符串。
    Symbol.unscopables:对象的Symbol.unscopables属性,指向一个对象。该对象指定了使用with关键字时,哪些属性会被with环境排除。

迭代器

ES6: for...of循环进行遍历。

原生具备iterator接口的数据:Array,Arguments,Set,Map,String,TypedArray,NodeList。

iterator接口:指的是对象内部的一个属性Symbol.iterator。

let nums = [1,2,3];
// for..of:n为键值。
// for..in:n为键名称。
for(let n of nums){
    console.log(n);
}
//迭代器
let iterator = nums[Symbol.iterator];

// 自定义迭代器事例
let person={
    name:"张三",
    works:["A","B"],
    [Symbol.iterator](){
        //索引
        let index = 0;
        return {
            //包含next函数
            next:() => {
                //返回值:value和done
                if(index < this.works.length){
                    let result = {value:this.works[index],done:false};
                    index++;
                    return result;
                }else{
                    return {value:undefined,done:true};
                }
            }
        };
    }
};

for(let w of person){
    console.log(w);
}

生成器

//1.基础用法
function * gen(){
    console.log("hello");
}
let it = gen();
//真正执行,输出hello
it.next();

//2.yield关键字:代码片段
function * gen(){
    console.log("hello-A");
    yield "A";
    console.log("hello-B");
    yield "B";
}

//返回迭代器对象
let it = gen();
it.next();//hello-A
it.next();//hello-B
for(let f of gen()){
    console.log(f);//输出的是yield内容
}

//3.生成器参数
function * gen(arg){
    console.log(arg);
    let one = yield 1;
    console.log(one);
    let two = yield 1;
    console.log(two);
}
let it = gen("A");
it.next("B");//A
it.next("C");//B
it.next();//C
  • 特殊的函数
  • 主要:异步编程,纯回调函数。

Promise诺言

//resolve成功->then第一个函数
//rejects失败->then第二个函数或catch
const p = new Promise(function(resolve,reject){
    //resolve(data);
    //reject(data)
});
p.then(function(data){
    //成功
},function(data){
    //失败
});
p.then(function(data){
    //成功
}).catch(function(data){
    //失败
});

//Promise.prototype.then:
//默认返回结果是Promise
//成功回调结果,则为返回的数据结果。
//抛出错误,失败的Promise
//可以链式调用。
  • 异步编程解决方案。
  • Promise是一个构造函数。

Set数据结构

类似于数组,但是成员的值都是唯一的,并实现了iterator接口。可以使用扩展运算符和for-of进行遍历。

let s=new Set();
let s1=new Set([1,2]);

//属性和方法
s1.size;//元素个数
s1.add(3);//添加新元素
s1.delete(3);//删除元素
s1.has(3);//是否存在
s1.clear();//清空
for(let a of s1){}//for-of操作。
let arr1=[...s1];//扩展运算符:1,2数组

//用途:去重
let arr=[1,2,3,2];
let arr2=[...new Set(arr)];

Map数据结构

类似于对象,键值对集合。但是键的类型不限于字符串,各种类型都可以当作键。

Map也事项了iterator接口,也可以使用扩展运算符和for-of进行遍历。

let m=new Map();
let m=new Map([["birth","201212"],["firstName","张"]]);

m.set("name","张三");//添加元素
m.size;//数据量
m.delete("name");//删除
m.get("name");//获取
m.clear();//清空
for(let a of m){
    //a类型为数组:[key,value]
}

class类

Es6引入了class的概念,作为对象的模板,通过class关键字定义。

可以看作是一个语法糖,绝大部分功能Es5都能实现,但是class写法让对象原型的写法更清晰,更像面向对象的语法。

class Person {
  //构造方法,名字固定不能修改
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  //方法结构必须方法名称加括号,不能使用ES5方式
  say() {
    console.log(`你好,${this.name}!`);
  }

  //静态属性方法:关键字static
  static maxAge = 200;
  static getMaxAge() {
    return maxAge;
  }
}

//继承:extends
class Worker extends Person {
  constructor(name, age, workAge) {
    super(name, age);
    this.workAge = workAge;
  }

  work() {
    console.log("工作");
  }

  //方法重写
  say() {
    console.log(`我是员工${this.name}!`);
  }
}

//get和set
class Dog {
  //get方法
  get name() {
    console.log("get name调用");
    return this.name;
  }

  set name(name) {
    console.log("set name调用");
    this.name = name;
  }
}
let dog = new Dog();
dog.name; //get使用方式
dog.name = "doudou"; //set方式

数值的扩展-Number

  • Number.EPSILON:javascript地 最小精度,值接近于:2.22E-16,主要用于浮点数运算地精度误差问题。
  • 进制形式:0b:二进制:let a=0b1010;0o:八进制:let b= 0o77;0x:十六进制:let c=0xaf;
  • Number.isFinite:检测数值是否为有限数,Number.isFinite(100);
  • Number.isNaN:检测数值是否为NaN。
  • Number.parseInt/Number.parseFloat:字符串转int/float。
  • Number.isInteger:是否为整数。
  • Math.trunc:将数字小数部分抹掉。
  • Math.sign:整数返回1,负数返回-1,0返回0。

对象方法地扩展-Object

  • Object.is(a, b):判断2个值是否i完全相等。
  • Object.assign(a, b):2个对象地合并。
  • Object.setPrototypeOf:设置原型对象。
  • Object.getPrototypeOf:获取原型对象。

模块化

模块化:大文件拆成小文件,然后将小文件合并起来。

好处:

防止命名冲突。代码复用。高维护性。


ES6之前地模块化规范有:

CommonJS:NodeJS,BrowserifyAMD:requireJSCMD:seaJS

ES6模块化规范:

  • export:定义对外接口。
  • import:定义输入模块。
//分别暴露
export let name="zhangsan";
export function say(){}

//统一暴露
let name="zhangsan";
function say(){}
export {
	name,
    say
};

//默认暴露
let name="zhangsan";
function say(){}
export default {
    name,
    say
};

//通用导入方式
import * as P from "test.js";

//解构赋值形式
import {name, say as hello} from "test.js";

//默认暴露的引入方式,2种方式等价
import {default as P} from "test.js";
import P from "test.js";
  • 浏览器使用模块化ES6的方式:
<script type="module">
    import * as P from "test.js"; 
    //一通操作
</script>
  • 浏览器另一种引入模块化ES6的方式:
<script src="./app.js" type="module"></script>
//app.js文件内部进行引入等一通操作
import * as P from "test.js"; 
//一通操作

4、ES7~ES11的新特性

ES7(ES2016)新特性

  • Array.prototype.includes:数组是否包含某个元素,返回boolean类型。
const a = [1, 2];
a.includes(1);
  • 指数操作符:[**]快速实现幂运算,功能与Math.pow相同。
let a=2 ** 10;//2的10次方=1024,等价:Math.pow(2,10);

ES8(ES2017)新特性

asyncawait让异步代码看起来跟同步代码一样。

    • async函数:返回值必须为promise对象,promise对象的结果由async函数执行的返回值决定。
//async函数
async function fn() {
  //返回结果不是一个promise类型的对象,返回结果就会是成功的promise。
  //return "hello";
    
  //抛出错误,返回结果是一个失败的promise
  //throw new Error("hello");
    
  //返回结果是一个promise对象。
}

let result = fn();
result.then((value) => {
    console.log("成功");
  }).catch((error) => {
    console.log("失败");
  });
    • await表达式:

await必须放到async函数中;

await右侧的表达式一般为promise对象。

await返回promise成功的值。

await的promise失败了,就会抛出异常,需要通过try-catch捕获处理。

//创建promist
function getUser() {
  return new Promise((resolve, reject) => {
    resolve("user info");
  });
}

//await必须要在async函数中
async function main() {
  try {
    //resolve成功数据
    let userInfo = await getUser();
    console.log(userInfo);
  } catch (error) {
    //reject失败数据
    console.error(error);
  }
}

Object.values和Object.entries:

let a = {name:"dd",age:12};

//对象所有的键
Object.keys(a);
//对象所有的值
Object.values(a);
//返回每个元素的键值数组[key,value]
Object.entries(a);
//属性描述对象
Object.getOwnPropertyDescriptor(a);

ES9(ES2018)新特性

  • rest参数和spread扩展运算符在ES6中已经引入,当时只针对数组,ES9中可以为对象提供支持。
function test({a, b, ...others}){
    console.log(a);
    console.log(b);
    console.log(others);
}
test({
    a:1,
    b:2,
    c:3,
    d:4
});
//输出:1,2,{c:3,d:4}

//对象扩展
let a ={name:"张三"};
let b={age:12};
let c = {...a,...b};//{name:'张三',age:12}
  • 正则扩展-命名捕获分组
//以前
let str = "<a href='http://nomax.cn'>诺码信科技</a>";
let reg = /<a href='(.*)'>(.*)<\/a>/;
let result = reg.exec(str);
console.log(result[1]); //http://nomax.cn
console.log(result[2]); //诺码信科技

//现在:?<url>
let str = "<a href='http://nomax.cn'>诺码信科技</a>";
let reg = /<a href='(?<url>.*)'>(?<text>.*)<\/a>/;
let result = reg.exec(str);
console.log(result.groups.url); //http://nomax.cn
console.log(result.groups.text); //诺码信科技
  • 正则扩展-反向断言:正向断言。
  • 正则扩展-dotAll模式。

ES10(ES2019)新特性

  • Object.fromEntries:把键值对数组转成了对象
//二维数组
let re=Object.fromEntries([
    ['name':'张三'],
    ['age', 20]
]);
  • String的trimStart和trimEnd:清除字符串前或后的空白字符。
  • 数组扩展方法:flat/flatMap:将多维数组转化为低维数组。
let arr=[1,2,[3,4]];
arr.flat();//1,2,3,4
//arr.flat(deep);--deep代表深度,默认1,如果三维数组展开,就需要传递2.

//flatMap可以看作是flat和map2个操作的结合。
let arr2=[1,2,3];
//以下2中方式等价
let arr3=arr2.map(item=>[item*10]);
let arr4=arr3.flat();
//flatMap方式。
let arr4=arr2.flatMap(item=>[item*10]);
  • Symbol.prototype.description:属性扩展,获取描述字符串
let s=Symbol("hello");
s.description;//返回hello

ES11(ES2020)新特性

  • 私有属性
class Persion {
  //公有属性
  name;
  //私有属性
  #age;
  constructor(name, age) {
    this.name = name;
    this.#age = age;
  }
}
  • Promise.allSettled:批量异步任务处理
const p1 = new Promise((resolve, reject) => {
  resolve("data1");
});

const p2 = new Promise((resolve, reject) => {
  reject("error2");
});

//返回成功的promise,内部结果数组对每个记录状态。
let re = Promise.allSettled([p1, p2]);

//有一个失败,就返回失败的Promise
let re2 = Promise.all([p1, p2]);
  • String.prototype.matchAll:字符串扩展,得到正常批量匹配的结果
  • 可选链操作符:?.
function main(config) {
  //原先的获取方式
  //let host = config && config.db && config.db.host;

  //现在-?.
  let host = config?.db?.host;
}

main({
  db: {
    host: "127.0.0.1",
    port: "3306",
  },
});
  • 动态import:按需加载
function btnClick() {
  //通过import函数动态导入模块,返回结果为promise,参数为导入模块
  import("./test01").then((module) => {
    module.sayHell("d");
  });
}
  • BigInt大整数数据类型
let n=222n;
typeof(n);//bigint
//普通值转biginit
BitInit(122);
//主要用于大整数的运算
  • globalThis全局对象
console.log(globalThis);

学无止境!

最近发表
标签列表