JavaScript--ES5和ES6(上)
一、概述
es表示ECMASCript ,他是从es3,es5,es6,es5是2009.12月发布的,es6是2015.6月发布的。vue2完全支持es5的(vue3完全支持es6的),react完全支持es6
二、es5的新特性
1、严格模式(对应的相反的称为怪异模式)
严格模式是一种不同的 JavaScript 解析和执行模型,ECMAScript 3 的一些不规范写法在这种模式下会被处理,对于不安全的活动将抛出错误。
'use strict'; //要对整个脚本启用严格模式,在脚本开头加上这一行
严格模式的特性
变量必须要带修饰符
"use strict";
a = 10
console.log(a); //a is not defined
函数里面this不能指向window
function sayHello(){
console.log(this); //undefined
}
sayHello()
不允许在非函数的代码块内声明函数
禁止八进制方法
函数的arguments数组形参和实参不同步
2、对于数组和字符串都进行了加强
数组的高阶函数(以函数做的参数的函数 称为高阶函数)
forEach
对数组每一项都运行传入的函数,没有返回值。
var arr = [1,2,3,4,5]
//forEach 遍历的 value表示里面的值 index表示里面的下标 array表示当前遍历的数组
var forEachObj = arr.forEach(function(value,index,array){
console.log(value); //打印里面的值 1,2,3,4,5
console.log(index) // 打印下标 0,1,2,3,4
console.log(array) //当前遍历的数组 [1,2,3,4,5]
})
map
对数组每一项都运行传入的函数,返回由每次函数调用的结果构成的数组。
//map 遍历的 value表示里面的值 index表示下标 array表示当前的遍历的数组
var mapObj = arr.map(function(value,index,array){
console.log(value); //打印里面的值 1,2,3,4,5
console.log(index) // 打印下标 0,1,2,3,4
console.log(array) //当前遍历的数组 [1,2,3,4,5]
return value+1
})
forEach和map的区别
- forEach没有返回值 里面没有return
- map有返回值 所以里面可以使用return关键词 他的返回值是一个数组
forEach和map的底层实现
//forEach方法实现
function forEach(fn){
//遍历这个arr
for(var i=0;i<arr.length;i++){
fn(arr[i],i,arr)
}
}
// map方法实现
function map(fn){
var res = []
//遍历这个arr
for(var i=0;i<arr.length;i++){
res.push(fn(arr[i],i,arr))
}
return res
}
reduce()和reduceRight()方法
这两个方法都会迭代数组的所有项,并在此基础上构建一个最终返回值。reduce()方法从数组第一项开始遍历到最后一项。而 reduceRight()从最后一项开始遍历至第一项。
传给 reduce()和 reduceRight()的函数接收 4 个参数:上一个归并值、当前项、当前项的索引和数组本身。这个函数返回的任何值都会作为下一次调用同一个函数的第一个参数。
//pre 前一个值 current 当前值 index 下标 array 数组
//reduce函数 利用前一个和后面值进行运算的操作 得出对应的值
var sum = arr.reduce(function(pre,current,index,arr){
return pre+current
})
console.log(sum);
reduce底层实现
// 底层实现reduce
function reduce(fn){
//如果只有一个直接返回
if(arr.length==1) return arr[0]
var res = arr[0]
//如果有多个的情况
for(var i=1;i<arr.length;i++){
res = fn(res,arr[i],i,arr)
}
return res
}
filter
对数组每一项都运行传入的函数,函数返回 true 的项会组成数组之后返回。
//filter返回的是一个数组 value index arr
var filterArr = arr.filter(function(value,index,arr){
return value>3
})
console.log(filterArr);
filter的底层实现
//实现filter函数
function filter(fn){
var res = []
//遍历数组
for(var i=0;i<arr.length;i++){
if(fn(arr[i],i,arr)){
res.push(arr[i])
}
}
return res
}
some
对数组每一项都运行传入的函数,如果有一项函数返回 true,则这个方法返回 true。
//some 一些 every 每一个
var value = arr.some(function(value,index,arr){
return value>4
})
console.log(value);//true
every
对数组每一项都运行传入的函数,如果对每一项函数都返回 true,则这个方法返回 true。
var value = arr.every(function(value,index,arr){
return value>4
})
console.log(value);//false
底层实现
//底层实现 some
function some(fn){
var isTrue = false
for(var i=0;i<arr.length;i++){
if(fn(arr[i],i,arr)){
isTrue = true
break
}
}
return isTrue
}
//底层实现 some
function every(fn){
var isTrue = true
for(var i=0;i<arr.length;i++){
if(!fn(arr[i],i,arr)){
isTrue = false
break
}
}
return isTrue
}
indexOf ()和lastIndexOf ()
-
这些方法都接收两个参数:要查找的元素和一个可选的起始搜索位置。
-
indexOf()方法从数组前头(第一项)开始向后搜索,而 lastIndexOf()从数组末尾(最后一项)开始向前搜索。
-
indexOf()和 lastIndexOf()都返回要查找的元素在数组中的位置,如果没找到则返回-1。
console.log(arr.indexOf(1,2));//从下标开始找 找这个1这个数字第一次出现的位置(左到右)
console.log(arr.lastIndexOf(1,5));//从下标5开始找 找1第一个次出现的位置(右到左)
字符串加强 (模板字符串 )
var a = 'hello'
console.log(`${a} world`) //hello world
es5新增的改变this指向的方法
bind (不会自动执行)
function say(){
console.log(this) //指向window
}
say() //打印window
//通过函数调用
var obj = { username:"jack" }
say.bind(obj)()//打印的this指向obj
call (自动调用函数)
// call 将this指向和某个内容联系在一块 自动调用 传参一个个用,隔开
say.call(obj,'tom','456')
apply (自动调用函数)
//apply 将this指向重新指向给对应的某个内容 自动调用 数组传递
say.apply(obj,['刘德华','123'])
call和apply的区别
- call传递的参数是一个个的内容,使用,隔开
- apply传递的参数是一个整个数组
三、es6的新特性
概述:es6对应数组 字符串 对象及函数以及循环,值类型,修饰符等都有加强(es6以后的内容都称为es6的内容)
1、数组的增强
find()和findIndex()
这两个方法都从数组的最小索引开始。find()返回第一个匹配的元素,findIndex()返回第一个匹配元素的索引。
var li = Array.from(lis).find(function(li){
return li.innerText == '5'
}) //找到对应匹配的元素
console.log(li);
//findIndex 查找对应的元素的下标 返回第一个找到的元素下标
var index = Array.from(lis).findIndex(function(li,index,arr){
return li.innerText == '5'
})
console.log(index);
静态方法(使用类名.)
Array.of() 和Array.from()
from()用于将类数组结构转换为数组实例,而 of()用于将一组参数转换为数组实例。
var array = Array.of(1,2,3,4,5)
console.log(array);
//具备某些数组的特性的对象称为伪数组 arguments NodeList HTMLCollection等
var lis = document.querySelectorAll('li')
// 伪数组是不具备数组的函数的
Array.from(lis).forEach(function(li){
console.log(li.innerText);
})
2、字符的增强
用于判断字符串中是否包含另一个字符串的方法:
-
includes : includes()检查整个字符串
-
startsWith :startsWith()检查开始于索引 0 的匹配项
-
endsWith :endsWith()检查开始于索引(string.length - substring.length)的匹配项
1)这些方法都会从字符串中搜索传入的字符串,并返回一个表示是否包含
的布尔值。
2)startsWith()和 includes()方法接收可选的第二个参数,表示开始搜索的位置。如果传入第二个参数,则意味着这两个方法会从指定位置向着字符串末尾搜索,忽略该位置之前的所有字符。
3)endsWith()方法接收可选的第二个参数,表示应该当作字符串末尾的位置。如果不提供这个参数,那么默认就是字符串长度。如果提供这个参数,那么就好像字符串只有那么多字符一样
- repeat
这个方法接收一个整数参数,表示要将字符串复制多少次,然后返回拼接所有副本后的结果
// indexOf的基础上增强
//是否包含 includes
console.log('abc'.includes('a')); //true
//endsWith 是否以这个字符串结尾
console.log('abc'.endsWith('abc'));//true
console.log('abc'.endsWith('c'));//true
//startsWith 是否以这个字符串开头
console.log('abc'.startsWith('a'));//true
console.log('abc'.startsWith('abc'));//true
//平铺 repeat 平铺的次数 重复多次的写个字符串
console.log('abc'.repeat(3));//将abc写3次
3、变量修饰符(增强)
- var 关键词:修饰的变量是伪全局变量(声明的变量会自动提升到函数作用域
顶部)
-
let 关键词 块状作用域 (变量名不能重复声明 避免变量名污染)
-
const 关键词 常量(声明变量时必须同时初始化变量,且尝试修改 const 声明的变量会导致运行时错误)
var btns = document.querySelectorAll('button')
// var 关键词声明的伪全局作用域
for(var i=0;i<btns.length;i++){
btns[i].onclick = function(){ //当前的事件是异步操作
console.log(i); //3 异步比同步晚执行 var关键词修饰的变量是伪全局变量
}
}
// let 块级作用域 只在当前的代码块内有用
for(let i=0;i<btns.length;i++){
btns[i].onclick = function(){ //当前的事件是异步操作
console.log(i); //3 异步比同步晚执行 var关键词修饰的变量是伪全局变量
}
}
// let 在同一作用域优点不能重复命名
let a = 10
// let a = 20 报错 不能重复声明
// 当你省略了对应的修饰符 默认就是以var关键词修饰
// const关键词 声明常量 他同样具备块级作用域 const定义的变量的不能重新赋值
// 声明的时候 必须要赋值
const a = 10
// a = 20 错误的 因为const修饰的变量不允许更改
// const b 错误的 必须要赋值
// es6 不是所有浏览器都可以直接解析的 不建议写源码的时候用let const (babel.js 解析es高版本的内容 把变成低版本的)
4、新增的值类型
旧有值类型
Number , String ,Boolean , Null , Undefined
新增的类型
Symbol
符号是原始值,且符号实例是唯一、不可变的。符号的用途是确保对象属性使用唯一标识符,不会发生属性冲突的危险。
bigInt 大的整型
//如果去声明一个Symbol
var v = Symbol() //独一无二的值
var s = Symbol('这个值很重要') //里面的参数是一个说明
var s1 = Symbol('这个值很重要') //里面的参数是一个说明
console.log(v);
console.log(s == s1);
console.log(s.description);//获取里面的详情信息 也可以设置 当前这个详情是一个只读属性 description
v.description = 'hello' //没用 他是个只读属性
//key是独一无二 当作对象的key值
var obj = {v:'hello'}
console.log(obj.v);
//bigInt 大的整型(存储number存不了的数据) 实现的方式 字符串传入实现
// 传入字符串
var str = '123456789123456789'
console.log( Number(str));
var bigNumber = BigInt(str)
console.log(bigNumber);
5、对象的增强
静态方法
is方法 Object.is() 判断俩个对象是否是一个(true或者false)
// NaN
console.log(NaN == NaN);//false
//Object.is 主要解决NaN和NaN的问题
console.log(Object.is(NaN,NaN));//true NaN是值类型(常量)
console.log(Object.is({},{}));//false {}对象
Object.assign 将后面对象合并当前前面 返回的是合并的对象
var obj = {sex:'男'}
//assign 目标对象 来源对象 将后面的合并到前面 返回一个对象 会影响之前的对象
var res = Object.assign(obj,{name:'张三',age:18})
console.log(obj);
console.log(res);
console.log(Object.is(obj,res));//true 浅拷贝( Object.assign)
6、函数增强
箭头函数
// //箭头函数一般都是匿名函数
// var hello = function(){ //之前的写法
// }
//箭头函数的写法 ()形参 {}代码块 把function省略了 加了个=>
var hello = ()=>{
console.log('hello')
}
//调用
hello()
箭头函数的简化
-
如果只有一个参数 可以省略()
// 简化 如果只有一个参数可以省略() var say = username => { console.log(username); } say('jack')
-
如果只有一句代码的话 可以省略{}
//当你只有一句代码的时候 {} 可以省略 var world = username => console.log(username) world('hello')
-
如果只有一句代码 且你需要返回数据情况下 可以省略对应的 retrun
//当你只有一句代码的时候 且你需要返回值 那么return可以被省略 var getUserName = username => username+'hello' var value = getUserName('张三') console.log(value); //张三hello //数组的forEach方法 [1,2,3].forEach(value=>console.log(value)) // 数组的reduce方法 var sum = [1,2,3].reduce((pre,current)=>pre+current) console.log(sum);
箭头函数的特性
- 箭头函数里面没有this(根据作用域链向上查找对应的this)
// this谁调用 this指向谁 是在对应的普通函数的情况下
// document.querySelector('button').onclick = function(){
// console.log(this);//指向当前按钮
// }
//箭头函数
document.querySelector('button').onclick = ()=>{
console.log(this); //箭头函数里面没有this 根据作用域链的情况 向上找 window
}
var hello = ()=>{
console.log(this);
}
hello.call({age:18}) // window
默认参数
function fn(agr1=value,arg2=value2){
}
// 初始化一个对象 默认值
function initObj(name,age=18,sex='男'){
return {
name,age,sex
}
}
console.log(initObj('jack'));//没有传参会使用默认值
console.log(initObj('jack',19,'女'));//传了参会覆盖默认值
7、对象里面内容的简化
属性的简化
简写属性名只要使用变量名(不用再写冒号)就会自动被解释为同
名的属性键。如果没有找到同名变量,则会抛出 ReferenceError。
var age = 18
var username = 'jack'
//简化 使用变量做键的名 {age:age,username:username}
var obj = {age,username}
函数的简写
var obj = {
say:function(){
console.log('hello')
}
}
obj.say()
//简写 省略:和function
var obj = {
say(){
console.log('hello')
}
}
obj.say()
8、循环的加强
- for in 是用于遍历对象的 遍历的是对象的里面key 他也可以遍历数组(数组也是对象)
- for of 是用于遍历数组的 遍历的是数组里面的value 他不可以遍历对象(只有实现了迭代器的对象才可以被遍历 必须具备length或者size属性)
如果要使用对应的for of来遍历对象的话 怎么办!!
Object的几个方法(静态方法) 可以用来实现对应的遍历
keys : 这个方法接收一个对象作为参数,返回包含该对象所有可枚举属性名称的字符串数组。
values: 这个方法接收一个对象,返回对象值的数组。
entries : 这个方法接收一个对象,返回键/值对的数组
var obj = {age:18,name:'jack',sex:'男'}
//keys 获取所有的key 作为一个迭代对象
var k = Object.keys(obj)
console.log(k);
//values 获取所有的value
var v = Object.values(obj)
//entries 获取所有的key-value对
var e = Object.entries(obj)
9、新增的对应的迭代器类型(实现了迭代器)
set 元素不重复的一个集合(去重)
set声明
无参
var set = new Set() //空的集合
将数组作为参数传递
var arr = [1,1,2,2,3,3]
var set = new Set(arr) //传入数组
console.log(set) //1 2 3
相关的方法(增删改查)
add 添加
delete 删除
clear 清空
keys 获取key
values 获取值
entries 获取键值对象
forEach 遍历(三个参数分别是value,key,set)
has 判断是否存在 (返回的是boolean类型)
属性
size 获取对应的长度
//无参的形式
var set = new Set()
//添加 add append push...
set.add(1)
set.add(2)
set.add(1)
//获取对应的set的长度 size
console.log(set.size);//2
//删除方法 delete remove
set.delete(1) //删除1这个value值
//删除所有 清空
// set.clear()
//获取元素
var key = set.keys() //获取所有key 值既是key 又是值
var value = set.values() //获取所有的值
var kv = set.entries() //获取所有的键值对
console.log(kv);
console.log(key);
console.log(value);
//set里面有一个forEach方法
// 第一个是值 第二个key 第三个是遍历的set
set.forEach((v,k,set)=>{
console.log(v);
})
//has 判断是否存在 返回true和false
console.log(set.has(2));//true
WeakSet 内容存储对应的set(只能存储对象 但并不能完成去重)
var weakset = new WeakSet()
weakset.add({username:"张三"})
weakset.add({username:"张三"})
weakset.add({username:"张三"})
console.log(weakset);//里面还是存在3个