ES5和ES6
文章目录
ECMAScript大纲
JavaScript构成
- BOM 对象
- DOM 对象
- ECMAScript 基础语法
ECMAScript概述
ECMAScript是对应的js基础语法,里面包含了除dom操作和bom操作外的所有内容。
ECMAScript主要拆分为两个单词ECMA(ecma一般指欧洲计算机制造商协会)、script(脚本)
ECMAScript简称es 主要的版本有ES3、ES5、ES6…(往后的版本也通常成为ES6)
但是不同es版本也有着相应的兼容问题,为了应对,通常可以使用Babel.js解决此问题
Babel 是一个广泛使用的 ES6 转码器,可以将 ES6 代码转为 ES5 代码,从而在老版本的浏览器执行。这意味着,你可以用 ES6 的方式编写程序,又不用担心现有环境是否支持。下面是一个例子。
ECMAScript的版本
-
ES3 (1999 年 12 月)基础版本
3.0 版是一个巨大的成功,在业界得到广泛支持,成为通行标准,奠定了 JavaScript 语言的基本语法,以后的版本完全继承。直到今天,初学者一开始学习 JavaScript,其实就是在学 3.0 版的语法。
-
ES5 (2009 年 12 月) 在es3上增强了对应的规范性以及应对方法
ES5 在 2013 年的年中成为 JavaScript 开发的主流标准,并在此后五年中一直保持这个位置。
-
ES6 (2015 年 6 月)在es5的基础上扩展了对应的类以及对应的处理
ES5新增内容
怪异模式
就是我们之前一直使用的开发模式,就叫怪异模式。因为很多时候出来的结果是非常怪异的,所以才称之为怪异模式。
严格模式
概述
即更严格的模式 在这种模式下执行,浏览器会对JS的要求更苛刻,语法格式要求更细致,更符合逻辑。
主流浏览器现在实现了严格模式。但是不要盲目地依赖它,因为市场上仍然有大量的浏览器版本只部分支持严格模式或者根本就不支持(比如 IE10 之前的版本)。严格模式改变了语义。*依赖这些改变可能会导致没有实现严格模式的浏览器中出现问题或者错误。谨慎地使用严格模式,通过检测相关代码的功能保证严格模式不出问题。最后,记得*在支持或者不支持严格模式的浏览器中测试你的代码。如果你只在不支持严格模式的浏览器中测试,那么在支持的浏览器中就很有可能出问题,反之亦然。
为什么需要严格模式
-
消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;
-
代码运行的一些不安全之处,保证代码运行的安全;
-
提高编译器效率,增加运行速度;
-
为未来的ECMAScript版本铺平道路
未来版本的 ECMAScript 很有可能会引入新语法,ECMAScript5 中的严格模式就提早设置了一些限制来减轻之后版本改变产生的影响。如果提早使用了严格模式中的保护机制,那么做出改变就会变得更容易。
书写方式
- 声明
use strict
在首行
<script>
'use strict'
n = 10;
console.log(n);
//Uncaught ReferenceError: n is not defined
</script>
特性
- 不可以省略var声明变量
- 禁止函数使用this关键字指向全局对象 (global)(winodw)
- 禁止使用八进制方法
- 不允许在非函数的代码块内声明函数(只能在上下文中)
- 函数名的参数唯一
- 严格模式下,arguments变量,形参是不会变(不同步)
数组新增的高阶函数
以函数作为参数的函数被称为高阶函数
有七个:forEach,map,filter,every,some,reduce,reduceRight
forEach
语法:数组名.forEach (function(当前值,当前下标,当前数组){})
作用: 遍历
返回: void
let arr = ['a','b','c','d']
//传入的函数为操作函数
//传入的函数有三个参数分别为遍历的值遍历的下标遍历的数组
arr.forEach(function(value,index,array){
console.log(value,index,array)
})
map
语法:数组名.map(function(当前值,当前下标,当前数组){})
作用: 遍历
返回: 一个数组
// map的使用和forEach是一样的唯一的区别在于forEach map有返回值
// map返回的是一个数组这个数组的个数一定和遍历的数组个数是一样的
let arr = ['a','b','c','d']
//传入的函数为操作函数
//传入的函数有三个参数分别为遍历的值遍历的下标遍历的数组
let nums = arr.map(function(value,index,array){
console.log(value,index,array)
if(i%2 == 0){
return i
}
})
console.log(nums)//[0, undefined, 2, undefined]
filter
语法:数组名.filter(function(当前值,当前下标,当前数组){过滤规则})
作用: 过滤
返回: 满足函数条件的数组
//fi1ter用于过滤,里面传入的对应的函数的返回值是boolean
//添加的返回的数组如果是false就不添加
//v表示对应的值 i表示下标array表示数组
let filterArr = ['a','b','c','ab'].filter(function(value,index,array){
return /a/.test(value)
})
console.log(filterArr)//['a', 'ab']
every
语法:数组名.(function(当前值,当前下标,当前数组){寻找规则})
作用: 遍历是否每个都满足条件
返回: Boolean
let arr = [1,2,3,4,5]
let result = arr.every(function(value,index,array){
return value>4
})
console.log(result)//false
some
语法:数组名.(function(当前值,当前下标,当前数组){寻找规则})
作用: 遍历是否存在满足条件
返回: Boolean
let arr = [1,2,3,4,5]
let result = arr.some(function(value,index,array){
return value>4
})
console.log(result)//true
reduce
语法:数组名.(function(前一个值,当前值,当前下标,数组){累加})
作用: 对数组中的每个元素进行累加,返回一个新的值,可以传入初始值
返回: 累计值
let arr = [1,2,3,4,5]
let result = arr.reduce(function(prv,value,index,array){
return prv + value
})
console.log(result)//15
reduceRight
语法:数组名.(function(前一个值,当前值,当前下标,数组){累加})
作用: 反向对数组中的每个元素进行累加,返回一个新的值,可以传入初始值
返回: 累计值
let arr = [1,2,3,4,5]
let result = arr.reduceRight(function(prv,value,index,array){
return prv + value
})
console.log(result)//15
this
Function对象的方法
bind
手动调用,返回一个函数
let obj = {
name: 'hello',
sayHello: function () {
console.log(this);
}
}
obj.sayHello()//{name: 'hello', sayHello: ƒ}
obj.sayHello.bind(window)();//bind返回的是个函数,需要自己调用//Window
apply
自动调用,返回值对应的函数执行的结果,传递的参数是对应的数组
let obj2 = {
name: 'world',
sayWorld: function (n1,n2) {
console.log(this);
console.log(n1+n2);
}
}
obj2.sayWorld(1,2) //{name: 'world', sayWorld: ƒ} 3
obj2.sayWorld.apply(window,[1,2])//Window 3
call
自动调用,返回值对应的函数执行的结果,传递的参数是一个个的元素
let obj3 = {
name: 'js',
sayJs: function (n1,n2) {
console.log(this);
console.log(n1+n2);
}
}
obj3.sayJs(1,2)//{name: 'js', sayJs: ƒ} 3
obj3.sayJs.call(window,1,2)//Window 3
区别
- bind返回的是一个函数,需要手动调用
- apply会自动调用函数,且返回的是对应的函数的执行结果(传递的参数是一个数组)
- call会自动调用函数,且返回的是对应的函数的执行结果(传递的参数是一个个的元素)
- bind函数执行完返回的函数不能被apply和call进行二次更改this指向
ES5其他新增
Array.trim()
去除前后空格
Array.isArray()
是否为数组
Array.indexOf()
查找相应的元素下标
Array.lastIndexOf()
从后面开始查找相应的元素下标
JSON.stringify()
序列化
JSON.parse()
反序列化
Object.defineproperty()
vue2中元素的动态绑定所使用过
getter setter(属于对象)
let obj = {
_name: 'hello',
get name() {
console.log('getter 调动了!');
return this._name
},
set name(value) {
this._name = value
console.log('setter 调动了!');
}
}
console.log(obj.name);//getter 调动了! hello
obj.name = 'world'//setter 调动了!
console.log(obj.name);//getter 调动了! world
ES6新增
变量声明
let
ES6 新增了let
命令,用来声明变量。它的用法类似于var
,但是所声明的变量,只在let
命令所在的代码块内有效。
// var 为全局作用域 会进行变量提升
for (var i = 0; i < 10; i++) {
setTimeout(function () {//异步
console.log(i); //打印10个10
})
}
// 块级作用域
for (let i = 0; i < 10; i++) {
setTimeout(function () {//异步
console.log(i); //打印0~9
})
}
const
const
声明的变量不得改变值,这意味着,const
一旦声明变量,就必须立即初始化,不能留到以后赋值。(地址不可变)
const n = 10;
// n = 9 //报错
const obj = {
name:'hello'
}
obj = {}//报错
obj.name = 'world'//不报错
字符串新增
字符串模板
let str1 = 'Hello'
let str2 = 'World!'
console.log(`${str1} ${str2}`)
includes() 是否包含
startsWith() 是否开头
endsWith() 是否结尾
repeat() 平铺(重复)
let str = 'abcdef'
// 第一个参数是检索的内容,第二个参数是指定的下标
// 是否开头
console.log(str.includes('bc'))//true
console.log(str.includes('bc', 2))//false
// 是否以开头
console.log(str.startsWith('a'))//true
// 是否以结尾
console.log(str.endsWith('f'))//true
// repeat 平铺(重复)
console.log(str.repeat(3))//abcdefabcdefabcdef
数组新增
Array.of()
将对应的内容填入Array返回数组
Array.from()
将伪数组转为数组
Array.find()
查找对应的内容
Array.findIndex()
查找对应的下标
/*示例*/
// Array.of
let arr = Array.of(1, 2, 3)
console.log(arr)//[1, 2, 3]
// Array.from
// 将三个表单这个伪数组转为数组,
let arr2 = Array.from(document.forms).filter(function (value) {
return value.action.includes('baidu')
})
console.log(arr2);//[form, form]
// Array.find
let arr3 = [1, 2, 3, 4]
let result1 = arr3.find(function (value, index, arr) {
return value > 3
})
console.log(result1);//4
// Array.findIndex
let arr4 = [1, 2, 3, 4]
let result2 = arr3.findIndex(function (value, index, arr) {
return value > 2
})
console.log(result2);//2
find()及findIndex()自定义实现
/*示例*/
//MyFind()
let str = [1, 2, 3, 4]
function MyFind(callback){
if(typeof(callback) !="function"){
throw new Error('参数传递错误')
}
for(let i = 0 ; i < str.length ; i++){
if(callback(str[i] , i , str)){
return str[i]
}
}
}
let result = MyFind(function(value ,index ,arr){
return value > 3
})
console.log(result);
/*示例*/
//MyFindIndex()
let str = [1, 2, 3, 4]
function MyFindIndex(callback){
if(typeof(callback) !="function"){
throw new Error('参数传递错误')
}
for(let i = 0 ; i < str.length ; i++){
if(callback(str[i] , i , str)){
return i
}
}
return -1
}
let result = MyFindIndex(function(value ,index ,arr){
return value > 3
})
console.log(result);
Array.fill()
覆盖为一个值
console.log([1,23,11].fill('a'));//['a', 'a', 'a']
console.log([1,23,11].fill('a',1));//[1, 'a', 'a']
Array.flat()
将多维数组变为一维数组
let arr1 = [[1],[2],[[3],[4]]]
let arr2 = []
//arr2 = arr1.flat(Infinity)//传入的是对应的层级,若不知道多少层,则传个最大值
arr2 = arr1.flat(Number.MAX_VALUE)//传入的是对应的层级,若不知道多少层,则传个最大值
console.log(arr2)//[1,2,3,4]
数据类型新增
es3就存在的
- string
- number
- Boolean
- object
- null
- undefined
es6新增
bigInt
大整型(存储不能存储的数据)
symbol
独一无二,数据唯一,无法重复(通过机器码实现独一无二)
注意声明时不使用new关键词
let bigInt = BigInt('1008610086100861008610086100861008610086100861008610086100861008610086100861008610086')
console.log(bigInt);//1008610086100861008610086100861008610086100861008610086100861008610086100861008610086n
//一般被当成对象的属性用于设计的而不是用于操作的
let symbol = Symbol('hello')
console.log(Symbol() == Symbol())//false
console.log(symbol.description)//hello
函数新增
默认参数
可指定参数的默认值
//ES6 之前,不能直接为函数的参数指定默认值,只能采用变通的方法。
function log(x, y) {
y = y || 'World';
console.log(x, y);
}
log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello World
//ES6 之后,可以直接为函数的参数指定默认值。
function log(x, y='World') {
console.log(x, y);
}
log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello World
箭头函数
标准写法(箭头函数是一个匿名函数)
let fn = (参数1,参数2)=>{
//代码块
}
简写
//若参数只有一个,则可以省略括号()
document.querySelector('button').onclick = e => {
console.log('点击了',e)
}
//若对应代码只有一行,则可以省略括号{}
document.querySelector('button').onclick = e => console.log('点击了1',e)
//若只有一行,省略的{},且需要返回值,可以省略 return
let fn = () => 'hello'
console.log(fn());//hello
特性
- 没有this (this会向外寻找)
- 没有arguments
- 箭头函数没有原型 (prototype)(不能被new)
object对象简写
let name = '张三'
let age = 18
//对象属性原本写法
let obj = {
name:name,
age:age
}
//简写 属性值一定是变量 属性名和属性值一致
let obj = {
name,
age
}
//函数原本写法
let fun = {
sayHello:function(){
console.log('hello')
}
}
// 简写
fun ={
sayHello(){
console.log('hello');
}
}
解构赋值
解构的概述就是将对应的对象或者数组解除对应的构造暴露其中的内容。
对象的解构赋值
根据属性名,快速提取对象中的属性,没有顺序要求,属性名正确即可
示例
let obj = {
name:'jack',
age:18
}
let {name,age} = obj
console.log(name)//jack
console.log(age)//18
数组的解构赋值
根据对应的顺序
示例
//数组的解构是对应的顺序的
let [a,b,c] =[1,2,3]
console.log(a)//1
扩展运算符
打开对应的对象或者数组将里面内容暴露出来
- 可以规定对应的参数不受限制 自动将对应的内容封装为一个数组
//接收不限制的参数
function sum(...args) {
//自动将对应的数据组装成一个数组
//args是一个数组
console.log(args)
//遍历args数组进行计算
return args.reduce((prev,current)=>prev+current)
}
console.log(sum(1,2,3,4,5,1,2,1,2,1))
//数组分割符 , es5的
var arr = [,,,,,]
console.log(arr)
- 打开对应的数组
// 利用...打开对应的数组
var arr = [{name:'张三'},{name:'李四'}]
var newArr = [...arr]
console.log(arr,newArr,newArr == arr)
//俩个数组组成一个数组
var arr1 = [1,2,3]
var arr2 = [4,5,6]
var newArr = arr1.concat(arr2)
console.log(newArr)
var newArr = [...arr1,...arr2] //对应的方法传参里面自动添加,
console.log(newArr)
- 打开对应的对象
//利用...来打开对象
var obj = {name:'jack',age:18}
var newObj = {...obj}
console.log(obj,newObj,newObj == obj)
generator函数
他是一个解决异步问题的一个函数 他可以将异步代码同步执行
yield next done
声明方式
function* fn(){
yield 代码片段
}
基础示例
function* fn(){
//分成一个段 断点
yield console.log(1)
yield console.log(2)
yield console.log(3)
yield console.log(4)
yield console.log(5)
}
var g = fn() //返回一个generator
var iter = g.return('a') //结束
console.log(iter) //done 是否完成 value返回的值
// g.throw() //抛出异常
// //next下一个
// g.next()
// g.next()
// g.next()
// g.next()
// g.next()
promise (es7新增)
他是一个解决异步问题的一个类 他可以将异步代码同步执行
then、catch方法来进行相关操作
三种状态:等待 成功 错误
ES6的模块化
模块化技术指代的是将对应的功能代码拆分为一个个的模块,完成对应的复用。
require.js的模块化(一个内容要导入必须先导出)
-
export 导出
//基础导出 一个文件只有一个 默认导出 第一种 export default { name:'jack', sayHi(){ console.log('hello') } } //导出变量的形式 第二种 export const name = 'tom' export const sayHi = ()=>{console.log('hello')}
-
import 导入
<!-- 支持es6的写法 --> <script type="module"> // import 名字 from 路径地址 默认导出的 导入的名字随便写 // import a from './export.js' //第一种导入 // a.sayHi() // console.log(a.name) // 导出多个的导入 第二种导入 import {sayHi,name} from './export.js' sayHi() console.log(name) </script>
重点 :AMD和CMD的区别
-
CMD和AMD都是为了JavaScript模块化开发的规范
-
CMD是sea.js推广过程中对模块定义的规范化产出;AMD是require.js推广过程中对模块定义的规范化产出
-
AMD是异步模块定义的意思,他是一个在浏览器端模块开发规范,由于不是JS原生支持,使用AMD规范进行页面开发时,需要对应的函数库
-
require.js解决的问题,多个JS文件可以有依赖关系,依赖关系&spm=1001.2101.3001.7020),被依赖的文件需要早于依赖它的文件加载到浏览器,JS加载的时候浏览器停止页面渲染,加载文件越多,页面失去响应时间越长
-
CMD通用模块定义,是国内发展的,有浏览器实现Sea.js,Sea.js要解决的问题和require.js一样,只不过模块定义的方式和模块加载时机有所不同
-
CMD 推崇依赖就近,AMD 推崇依赖前置
Class 类
ES6提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。
练习
/*
3.编写⼀个动物类,该类包含name的属性,和say的⽅法。
通过say⽅法可以打印动物说话了。编写⼀个Dog类继承动物类.
要求:
该类中包含颜⾊的属性,该类重写say⽅法,要求打印⽗类的say⽅法⾥的内容,
并且打印 动物颜⾊+动物名字+“叫了”。(备注狗会一直叫)
*/
class Animals {
constructor(name){
this.name = name
}
say(){
console.log(this.name+',说话了!');
}
}
class Dog extends Animals {
constructor(name,color){
super(name)
this.color = color
}
say(){
console.log(this.color+'的'+this.name+',叫了!');
}
}
let dog = new Dog('哈士奇','黑白色')//黑白色的哈士奇,叫了!
dog.say()
Set
数据结构Set类似于数组,但是成员的值都是唯一的,没有重复的值。
var set = new Set([1,2,3,4,5,5,5,5]);
console.log(set.size); // 5
Set的属性和方法:
- size : 数量
- key():获取所有的key
- values():获取所有的values
- add(value):添加某个值,返回Set结构本身
- delete(value):删除某个值,返回一个布尔值,表示删除是否成功
- has(value):返回一个布尔值,表示该值是否为Set的成员
- clear():清除所有成员,没有返回值
WeakSet
WeakSet和Set一样都不存储重复的元素, 用法基本类似,但有一些不同点, WeakSet的成员只能是对象,而不能是其他类型的值。
Map
Map 是一个“超对象”,其 key 除了可以是 String 类型之外,还可以为其他类型(如:对象) let map = new
let map = new Map([[1, 'one'],[2, 'two'],[3, 'three']]);
Map的属性方法和 Set 差不多:
- size:返回成员总数
- set(key, value):设置一个键值对
- get(key):读取一个键
- has(key):返回一个布尔值,表示某个键是否在Map数据结构中
- delete(key):删除某个键
- clear():清除所有成员
- keys():返回键名的遍历器
- values():返回键值的遍历器
- entries():返回所有成员的遍历器
Map和Set的异同
同
- map和set一样是关联式容器,它们的底层容器都是红黑树
- 两种方法具有极快的查找速度
- Map 和 Set 都不允许键重复
异
-
初始化需要值不一样,Map需要的是一个二维数组,而Set 需要的是一维 Array 数组。
-
Map 是键值对的存在,键和值是分开的
-
Set 没有 value 只有 key,value 就是 key
-
size : 数量
-
key():获取所有的key
-
values():获取所有的values
-
add(value):添加某个值,返回Set结构本身
-
delete(value):删除某个值,返回一个布尔值,表示删除是否成功
-
has(value):返回一个布尔值,表示该值是否为Set的成员
-
clear():清除所有成员,没有返回值
WeakSet
WeakSet和Set一样都不存储重复的元素, 用法基本类似,但有一些不同点, WeakSet的成员只能是对象,而不能是其他类型的值。
Map
Map 是一个“超对象”,其 key 除了可以是 String 类型之外,还可以为其他类型(如:对象) let map = new
let map = new Map([[1, 'one'],[2, 'two'],[3, 'three']]);
Map的属性方法和 Set 差不多:
- size:返回成员总数
- set(key, value):设置一个键值对
- get(key):读取一个键
- has(key):返回一个布尔值,表示某个键是否在Map数据结构中
- delete(key):删除某个键
- clear():清除所有成员
- keys():返回键名的遍历器
- values():返回键值的遍历器
- entries():返回所有成员的遍历器
Map和Set的异同
同
- map和set一样是关联式容器,它们的底层容器都是红黑树
- 两种方法具有极快的查找速度
- Map 和 Set 都不允许键重复
异
- 初始化需要值不一样,Map需要的是一个二维数组,而Set 需要的是一维 Array 数组。
- Map 是键值对的存在,键和值是分开的
- Set 没有 value 只有 key,value 就是 key