JavaScript的构成
- DOM 操作文档的
- BOM 操作浏览器
- ECMAScript (基础语法)
ECMAScript
ECMAScript简称为ES,(ECMA 欧洲计算机协会),ES分为不同的版本(常用的版本 ES3(常用的所有浏览器都支持 都可以直接解析)、ES5 (大部分的高版本的浏览器都能支持)、ES6(部分浏览器支持 但存在兼容问题 不能直接解析 必须先编译成ES3才能解析 bable.js(es的版本编译的)、ES7...(一般把ES6以后都称为ES6)))
- ES3 (常用版本)
- ES5 (更加规范化和更加简易化 2015.10)
- ES6 (模块化编程 基于ES5更加简易化 2016.4)
ES5新增内容
严格模式
概述:我们普通书写的js代码 并没有特别多的规范,甚至在某些时候可以随意发挥,这种模式被称为怪异模式。相对而言一种更加规范化的模式被称为严格模式。
严格模式的声明
使用 use strict 进行声明,他的声明位置必须在第一行 (常用于源码书写)
严格模式的特性
- 声明一个变量必须具备关键词
- 函数内this不能指向window
- 函数内arguments形参和实参不同步
- 禁止八进制方法
- 函数声明必须在对应的位置进行声明
//怪异模式
// var a = 10
// b = 20
// console.log(a);
// console.log(b);
//严格模式
"use strict"; //声明必须在第一行
//声明一个变量必须要有关键词
c = 30
console.log(c);//c没有被定义
//严格模式中函数内的this不能指向window
function fn(){
console.log(this);
}
fn()// this 是 undefined
//在严格模式中不能使用八进制相关的方法
//严格模式中argument的形参和实参不同步
//严格模式中函数只能在对应的声明函数地方进行声明
数组新增的高阶函数
高阶函数概述:
以函数作为参数的函数叫做高阶函数
新增的相关函数
遍历的函数
- forEach (没有返回值)
//高阶函数
var arr = ['a','b','c']
//forEach
//传入的函数里面的三个参数分别是 第一个值 第二个下标 第三个遍历的数组
//forEach没有返回值 js函数里面参数如果不需要可以不传
arr.forEach(function(v,i,arr){
// console.log(v); //里面值
// console.log(i); //下标
console.log(arr); //遍历的数组
})
//省略对应参数
arr.forEach(function(v){
console.log(v);
})
- map (返回值是一个数组)
//map
//map跟forEach使用是一样的 但map有返回值 返回一个数组
var mapArr = arr.map(function(v,i,arr){
console.log(v);
})
console.log(mapArr);//[undefined,undefined,undefined]
var mapArr = arr.map(function(v,i,arr){
console.log(v);
return v+i+'你好'
})
console.log(mapArr);
过滤和对应计算的
- filter (返回一个数组)
var arr = ['abc','a','bc']
//filter 过滤 传入对应的函数 通过函数来返回条件进行过滤 返回的值为数组
//第一个为值 第二位下标 第三为当前遍历的数组
var filterArr = arr.filter(function(v,i,arr){
//里面包含a返回true 里面没有a返回false
//如果返回值是false 就不会加入到对应的数组 如果返回值为true就会加到对应的数组
return /a/.test(v)
})
console.log(filterArr);//包含a的一个数组 ['abc','a']
var arr = [10,9,8,23,15]
//返回所有大于10的
var filterArr = arr.filter(function(v){
return v>10
})
console.log(filterArr);//[23,15]
var arr = [10,9,8,23,15]
- reduce (从前到后 返回一个值)
- reduceRight (从后往前 返回一个值)
//reduce 计算的 计算所有的和
//prev表示前面的总和 第一次prev值为10 第二次为19 current默认从第二个开始
var sum = arr.reduce(function(prev,current,i,arr){
console.log(prev);
console.log(current);
console.log(i);//1
return prev+current
})
console.log(sum);
//调整到第1个开始 current的下标为0
arr.reduce(function(prev,current,i,arr){
console.log(i);//0
console.log(prev);//0
},0)
//求乘积
var v = arr.reduce(function(prev,current){
return prev * current
})
console.log(v);
//reduceRight 从右边开始 从后到前 prev值就是倒数第一个 i从倒数第二个开始
arr.reduceRight(function(prev,current,i,arr){
console.log(i);
})
判断是否存在
- some (只要有一个就返回true)
// 查询的相关 条件在于传入的函数的返回的值
var arr = [0,1,2,3]
//根据里面返回的内容来进行判断的 里面只要有true返回 他就是true
var is = arr.some(function(v,i,arr){
return v>2
})
console.log(is);
- every (所有都满足条件返回true 不然返回false)
//every 每一个都要满足条件
var is = arr.every(function(v,i,arr){
return v>=0
})
console.log(is);
注意事项
- forEach和map的区别(forEach没有返回值 map有返回值)
- reduce是用于计算的 reduce传入的函数有四个参数(前面的和(默认为第一个) 当前的值(默认是第二个开始) 当前的下标(默认从1开始) 当前遍历的数组)如果需要调整在后面进行传参。
- some和every的区别 (some只要有一个满足条件就返回true every要每个都满足条件才返回true)
手写实现数组的高阶函数
- forEach(遍历没有返回值)
var arr = [1,2,3]
//forEach 传入的fn里面要有三个参数分别是值 下标 遍历的数组
function myForEach(fn){
//使用for循环
for(var i=0;i<arr.length;i++){
//调用传入的函数
fn(arr[i],i,arr)
}
}
//调用
myForEach(function(v,i,arr){
console.log(v);//1,2,3
console.log(i);//0,1,2
console.log(arr);//[1,2,3]
})
- map (返回一个数组)
var arr = [1,2,3]
//map 返回一个数组 数组里面值就是当前的函数执行后的返回结果
function myMap(fn){
//准备一个返回的数组
var returnArray = []
//使用for循环遍历
for(var i=0;i<arr.length;i++){
//将传入的函数的返回结果接收
var result = fn(arr[i],i,arr)
//添加到对应的返回数组中
returnArray.push(result)
}
//将数组返回
return returnArray
}
//调用
var mapArray = myMap(function(v,i,arr){
return v+'你好'
// console.log(v);
})
console.log(mapArray);//['1你好','2你好'],'3你好']]
- filter (返回数组)
var arr = [1,2,3]
//filter 过滤 返回一个数组
function myFilter(fn){
//准备返回的数组
var returnArray = []
//遍历
for(var i=0;i<arr.length;i++){
//接收传入函数的返回值
var flag = fn(arr[i],i,arr)
//判断当前的函数是否返回值为true 为true加入到对应的数组
if(flag){
returnArray.push(arr[i])
}
}
return returnArray
}
//调用
var filterArray = myFilter(function(v){
return v>1
})
console.log(filterArray);//[2,3]
- reduce (返回的是值)
var arr = [1,2,3]
//reduce实现
function myReduce(fn,index){
//默认情况下第一次的prevoiseValue值为第一个
var prevoiseValue = arr[0]
//默认的index从1开始
if(typeof index != 'number'){
index = 1
}else{//传入了对应的index就是0 prevoiseValue值也是0
index = 0
prevoiseValue = 0
}
//遍历
for(var i=index;i<arr.length;i++){
//调用方法 将对应前面计算的值给到对应的prevoiseValue
prevoiseValue = fn(prevoiseValue,arr[i],i,arr)
}
return prevoiseValue
}
//调用
var result = myReduce(function(prev,current){
return prev*current
})
console.log(result);//6
- some (返回boolean类型 有true返回true 没有返回false)
var arr = [1,2,3]
//some 里面有一个return true 他就返回true 否则返回false
function mySome(fn){
//遍历
for(var i=0;i<arr.length;i++){
//接收对应的函数执行的返回值
var flag = fn(arr[i],i,arr)
//如果返回值有一个为true
if(flag){
//直接返回true
return true
}
}
//默认返回false
return false
}
//调用
var is = mySome(function(v){
return v>2
})
console.log(is);//true
- every (返回boolean类型 如果有false就返回false 没有返回true)
var arr = [1,2,3]
//every
function myEvery(fn){
//遍历
for(var i=0;i<arr.length;i++){
//接收对应的函数执行的返回值
var flag = fn(arr[i],i,arr)
//如果返回值有一个为false
if(!flag){
//直接返回false
return false
}
}
//默认返回true
return true
}
//调用
var is = myEvery(function(v){
return v>0
})
console.log(is);//true
字符串新增
字符串模板
var username = '李丹'
var str = `hello${username}`
console.log(str) //hello李丹
改变this指向新增方法
this指向
- this在函数内的this指向当前函数的调用的者(全局调用的函数this指向window)
- this在对应的对象内的函数指向当前的对象的
- this在事件对应的函数内指向当前事件的目标元素
如果需要更改this指向那么我们可以给对应的函数调用对应的方法
相关方法
- bind (手动调用)
- apply (自动调用 传递一个数组)(* 如果传递的是数组)
- call (自动调用 一个个的数据传递)(* 一般常用)
function fn(arg,arg1){
console.log(this);
console.log(arg,arg1);
}
fn() //打印window
var obj = {name:'jack'}
//调用bind方法来更改this指向
//将对应的函数绑定给obj这个对象 bind不会执行函数
//函数调用的bind方法返回的是一个函数 这个函数不会自动调用 需要你手动调用
var v = fn.bind(obj)
//执行函数
v()
//bind方法运用 需要手动调用需要()来调用 传参传入到对应的()里面
fn.bind(obj)('你好','世界')
//apply 自动调用 第一个参数是绑定的对象 第二个参数是传递的参数(以数组进行传递)
fn.apply(obj,['hello','world'])
//call 自动调用 第一个参数是绑定的对象 第二个参数是传递的参数 (以一个个的元素进行传递)
fn.call(obj,'吃饭了吗','睡觉了吗')
apply方法和call方法的区别
- apply方法传递的参数以数组形式
- call方法传递的参数以元素形式
共同点
- apply方法和call方法都会自动调用对应的函数
ES6新增内容
ES6对于字符串,数组,函数,对象,循环,变量修饰关键词、基础数据类型等都有新增
字符串新增方法
- startsWith 是否开头
- endsWith 是否结尾
- includes 是否包含
- repeat 平铺
var str = 'abc'
//是否开头 返回boolean类型
//是否以a开头
console.log(str.startsWith('a'));//true
// 是否结尾 返回boolean类型
//是否以a结尾
console.log(str.endsWith('a'));//false
//是否包含 返回boolean类型
//是否包含ac
console.log(str.includes('ac'));//false
//平铺 返回的是一个新的字符串
var newStr = str.repeat(2) //将对于的abc平铺俩遍
console.log(newStr);//abcabc
数组新增方法
普通方法
- find 根据条件查找对应的值
- findIndex 根据条件查找对应的下标
var arr = [1,2,3]
//普通方法(高阶函数) find findIndex
//根据条件查找 返回找到的第一个内容 没有找到返回undefined
//第一个是值 第二个是下标 第三个是数组
var value = arr.find(function(v,i,arr){
return v>1
})
console.log(value);//2
//根据条件返回找到第一次出现的下标 没有找到返回-1
var index = arr.findIndex(function(v,i,arr){
return v>1
})
console.log(index);//1
手写实现find及findIndex
//find查找值 根据传入函数的返回值作为条件来查找 没有找到返回undefined
var arr = [1,2,3]
function myFind(fn){
//遍历 调用函数
for(var i=0;i<arr.length;i++){
var flag = fn(arr[i],i,arr)
if(flag){
return arr[i]
}
}
}
//findIndex查找下标 根据传入函数的返回值作为条件来查找 没有找到返回-1
function myFindIndex(fn){
//遍历 调用函数
for(var i=0;i<arr.length;i++){
var flag = fn(arr[i],i,arr)
if(flag){
return i
}
}
return -1
}
var value = myFind(function(v){
return v>1
})
var index = myFindIndex(function(v){
return v<1
})
console.log(value,index);
静态方法
- Array.from 将对应的伪数组转为数组
- Array.of 将对应的传入的元素组成一个新的数组返回
//新增的俩个静态方法
//将伪数组转为数组
var btns = document.querySelectorAll('button') //NodeList 伪数组
// btns.map(function(v){
// console.log(v);
// }) 出错 伪数组没有map方法
//转成数组以后再调用
Array.from(btns).map(function(v){
console.log(v);
})
//将传进去的内容组成一个新的数组出来 返回对应的数组
var newArray = Array.of('a','b','c')
console.log(newArray);
变量修饰关键词
es3存在
- var 声明伪全局变量
新增的
- let 声明块状作用域变量(不允许重复声明 只在当前的代码块内起作用(块级作用域))
- const 声明常量 (声明必须赋值 不允许修改 块级作用域)
// let 声明块级作用域
let a = 10
// let a = 20 不允许重复声明
a = 20
console.log(a);
// 块状作用域及伪全局作用域
for(var i=0;i<5;i++){
setTimeout(function(){
console.log(i);//重复打印五次5
},1000)
}
//块级作用域 只在当前的作用范围内容 进入
for(let i=0;i<5;i++){
setTimeout(function(){
console.log(i);//打印0 1 2 3 4
},1000)
}
// const 声明常量
const b = 10
// b = 20 //不允许二次赋值
console.log(b);
//声明必须要赋值
// const c 错的
//const也是块级作用域
基础数据类型
ES3的基础值类型
- String
- Number
- Boolean
- null
- undefined
新增的值类型
- symbol 独一无二的值
- BigInt 大的整型
// 新增的类型
//独一无二的值(栈上面)
var sym = Symbol()
var sym1 = Symbol()
console.log(sym);
console.log(sym == sym1);//false
var sym2 = Symbol('你好') //传入的参数是说明
var sym3 = Symbol('你好')
console.log(sym2 == sym3);//false
//一般用于对象的key key不能重复的
var obj = { sym:10}
console.log(obj.sym);
//获取详情
console.log(sym2.description);
//BigInt 大的整型 容纳大的数
//Number中的整型Int容纳范围是有限的 10^16
var bi = BigInt('111111111111111111111111111111111111111111111111111111111111111')
console.log(bi);
循环
- for in(遍历对象)
- for of (遍历数组的 只要实现了iterator迭代器就可以用for of遍历)
var obj = {
name: '张三',
age: 18
}
for (var key in obj) { //遍历的是key (数组的key是下标)key的类型为字符串
console.log(key)
}
var arr = ['a', 'b', 'c']
for (var value of arr) { //for of遍历的是值
console.log(value)
}
函数的新增
新增函数的默认参数
// 函数新增 默认参数
//默认a为0 b也为0 如果你传递了对应的参数 那么默认值就会被覆盖
function fn(a=0,b=0){
console.log(a+b);
}
fn(1,3)//打印4
fn()//打印0
fn(1)//打印1
新增箭头函数
箭头函数的写法
(参数1,参数2,...参数n)=>{代码}
示例
//新增箭头函数 是一个匿名函数
var fn1 = ()=>{
console.log('我是箭头函数');
}
fn1()
箭头函数的简化写法
- 如果当前的参数只有一个 ()可以省略的
- 如果当前的{}里面的代码只有一句的话 {}也可以省略
- 如果当前的{}里面只有一句代码 且你需要返回数据的时候 可以省略return
//简化写法
// 如果当前的参数只有一个 ()可以省略的
// 如果当前的{}里面的代码只有一句的话 {}也可以省略
// 如果当前的{}里面只有一句代码 且你需要返回数据的时候 可以省略return
var fn2 = arg =>arg+'你好' //当前fn2 传递一个arg 返回一个arg+你好
var result = fn2('hello')
console.log(result);
箭头函数的特性
- 没有this (根据作用域链向上找)
- 没有arguments
//箭头函数的特性
var obj = {
say:function(){
console.log(this);
console.log(arguments);
}
}
obj.say() //打印obj
var obj = {
say:()=>{
console.log(this);
console.log(arguments);
}
}
obj.say() //打印window
//箭头函数里面没有this 所以他会去上面找 根据作用域链找离他最近的
//箭头函数里面没有arguments