1、let
块级作用域
(1)函数内部
(2)块中(通常指的是一对花括号之间)
特性:
①let 定义的变量不会被提升是
②在同一个作用域下,let不能重复定义两个同名的标识符
在不同的作用域下,可以使用同名的标识符
③var在全局作用域下,会把属性绑定到window上,从而可能产生覆盖属性的隐患,
而let关键字只是会遮蔽它,并不会覆盖window上的同名属性(let的定义的不会挂载到window上去)
//不会被提升
console.log(a) //a is not defined
let a=10
console.log(a) // undefined
var a=10
//块级作用域
let a=10;
if(a){ //a输入转换成true
let a=100;
console.log(a); //100
}
console.log(a) //10
//重名
var a=10;
let a=100;//报错,会去前面找有没有a这个名字
//不在let上,不会覆盖window上的同名属性
var a=10;
console.log(a);//10
console.log(window.a);//10
console.log('a' in window )//true 判断a是否在window下的属性(要用引号引起来)
//声明正则表达式的方式
//var RegExp
//var re=new RegExp();
//var re=//
//把全局正则表达式替换(全局表达式是构造函数)
var RegExp="aaa";
console.log(RegExp); //aaa
console.log(window.RegExp) //aaa
console.log('RegExp' in window) //true RegExp被认为是变量在winodw上
let RegExp="aaa";
console.log(RegExp); //aaa
console.log(window.RegExp) // RegExp() { [native code] } -->是正则表达式上的
console.log('RegExp' in window) //true RegExp被认为是变量在winodw上
let经典应用(选项卡)
<input type="button" value="点我1" />
<input type="button" value="点我2" />
<input type="button" value="点我3" />
window.onload=function(){
var aBtn=document.querySelectorAll("input");
//自定义属性
/* for(var i=0;i<aBtn.length;i++){
//给按钮加自定义属性
aBtn[i].index=i
aBtn[i].onclick=function(){
alert(this.index) //用this访问到他的自定义属性
}
}
*/
//闭包做法
/* for(var i=0;i<aBtn.length;i++){
aBtn[i].onclick=(function(j){
return function(){
alert(j)
}
})(i)
}
*/
//let块级作用域
for(let i=0;i<aBtn.length;i++){
aBtn[i].onclick=function(){
alert(i)
}
}
}
2、const(用来定义常量)
特性:
①块级作用域
②声明的时候,必须赋予初始值
③不能被重新赋值
④如果值时一个对象,那么对象里面的属性是允许被修改的(引用类型)
⑤不能跟其他标识符重名
//不能被重新赋值
const a=10;
a=100
console.log(a) //报错
//重定义错误
let a=10;
const a=10;
//重定义错误
var a=10;
const a=10;
//重定义错误
const a=10;
const a=10;
//块级作用域
{
const a=10;
}
console.log(a)//报错
//const定义的常量对象,只能修改里面的属性值,不能把整个对象修改
const user={
'name':'aaa'
}
user.name='bbb'
console.log(user.name)//bbb
const user={
'name':'aaa'
}
user={ //报错
'age':22
}
3、for循环中的var,let,const
//往数组添加10个匿名函数
var fns=[];
for(let i=0;i<10;i++){
fns.push(function(){
console.log(i)
})
}
fns.forEach(function(fn){ //打印fns的每一项
fn();
})
//0
//...
//9
//没有let可以用立即表达式存储
var fns=[];
for(var i=0;i<10;i++){
fns.push((function(j){
return function(){
console.log(j)
}
})(i))
}
fns.forEach(function(fn){
fn();
})
//const的常量不能被修改
for(const i=0;i<10;i++){
}
//const只读不改的话,可以正常使用
var userList={
'name1':'aaa',
'name2':'bbb',
'name':'ccc'
}
for(const key in userList){
console.log(key+'---->'+userList[key])
}
//临时死区
console.log(typeof a);//undefined 判断是否存在a
if(true){
console.log(typeof a);// a is not defined 检查a存不存在
let a=10;
}
//console.log(typeof a); //undefined 放外面是没问题的
4、箭头函数(是一种使用箭头( => )定义函数的新语法)
//没有参数的时候
let show=function(){
console.log('aaa')
}
show();
//箭头函数写法
let show=()=> console.log('aaa');//只有一句话不能打大括号
show();
//或者
let show=()=> { console.log('aaa'); }
show();
//或者
let show=()=> 'aaa' //‘aaa’代表返回值,前面省略return关键字
//等价于
//let show=function(){ return 'aaa'}
console.log(show());
//一个参数时
let show= a => a; //有一个参数可以省略小括号 let show=(a)=>a;
//如果要加花括号,要加上return关键字 let show= a =>{return a};
//等价于
//let show=function(a){ return a;}
console.log(show(10))
//两个参数时不能省略小括号
let add=(a,b)=> console.log(a+b) //也可以加花括号let add=(a,b)=>{ console.log(a+b)}
add(10,20)
//或者
let add=(a,b)=> {return a+b}
console.log(add(10,20))
特性:
①不能通过new关键字调用
②没有原型
③没有arguments对象,但是可以获取到外层函数的arguments
//问题:函数体的花括号,还是对象定义的花括号
//let show=(name)=>{'userName':name}
//解决方法一:在外面加小括号,代表返回一个对象,
let show=(name)=>({'userName':name})
//解决方法二:如果不用小阔括号用花括号就要用return
//let show=(name)=>{return {'userName':name}}
let oUser=show('aaa')
console.log(oUser.userName)
//两个参数时
let show=(name,age)=>{
return {
'userName':name,
'userAge':age
}
}
let oUser=show('aaa',22)
console.log(oUser.userName,oUser.userAge)
-------------------------------------------------------
//立即表达式的箭头函数
//(function(){})()
let oUser=((uName,uAge)=>{
return {
'userName':uName,
'userAge':uAge
}
})('aaa',22)
console.log(oUser.userName,oUser.userAge)
-------------------------------------------------------
//不能通过new调用
//let Show=function(){}
//new Show();//可以当做构造函数调用
let Show=()=>{} //报错
new Show();
-------------------------------------------------------
//箭头函数没有原型对象, 普通函数有原型对象
//let Show=function(){}
//console.log(Show.prototype)
let Show=()=>{}
console.log(Show.prototype) //undefined
//箭头函数没有argument(获取函数的参数集合)
//let Show=function(){
// console.log(arguments)
//}
//Show(10,100,20)
let Show=()=>{
console.log(arguments) //arguments is not defined
}
Show(10,100,20)
//但是箭头函数可以获取外部的非箭头函数的arguments集合
let Show=function(){//找的是外面的这个非箭头函数的arguments的集合
return ()=>{
console.log(arguments); [10,100,20]
}
}
Show(10,100,20)()
④箭头函数中的this,取决于他的上层非箭头函数的this指向
call,apply,bind不能改变箭头函数的this指向
//函数的
//题一:
var a=10;
let show=()=>{
console.log(this.a)//10 箭头函数指向他的上层非箭头函数(window)的this
}
show();
//题二:
let a=10; //let定义的会不挂载到window上,也不会提升
let show=()=>{
console.log(a) //10 let的块作用域找到
console.log(this.a)//undefined
}
show();
//题三:
let a=10; //let定义的会不挂载到window上,也不会提升
let show=()=>{
let a=100;
console.log(a) //100 let的块作用域找到的是本身的
console.log(this.a)//undefined
}
show();
//题四:
let n1=10,n2=20; //let定义的会不挂载到window上,也不会提升
let add=()=>{
console.log(this.n1+this.n2) //NaN undefined+undefined=NaN
}
add()
-------------------------------------------------------
//对象的
var a=100;
var obj={
a:10,
show:function(){
return ()=>{
return this.a //10 他的上一层非箭头函数show
}
}
}
console.log(obj.show()())
-------------------------------------------------------
//构造函数
function User(name){
this.name=name;
this.getName=()=>{
return this.name //this指向他的上一层非箭头函数即new User('aaa')
}
}
console.log(new User('aaa').getName())
-------------------------------------------------------
//函数表达式
var a=100;
var obj={
a:1
}
let show=function(){
let fn=()=>{
console.log(this.a)
}
fn()
}
show();//100 this指向的是show,show又是window的
show.call(obj);//1 call改变this指向,this指向obj
-------------------------------------------------------
//普通函数可以通过 call,apply,bind改变this指向
let show=function(){
console.log(this)
}
show(); //window
show.call('abc'); //abc
show.apply('def'); //def
var fn=show.bind('hello'); //bind绑定后返回新的函数
fn();
//箭头函数不能通过call,apply,bind改变
let show=()=>{
console.log(this)
}
show(); //window
show.call('abc'); //window
show.apply('def'); //window
var fn=show.bind('hello'); //window
fn();
5、示例es6的简写:
排序
//排序
var arr=[10,200,30,5,0,1000];
arr.sort(function(a,b){
return a-b;
})
console.log(arr)
//es6排序
var arr=[10,200,30,5,0,1000];
arr.sort((a,b)=> a-b )
console.log(arr)
全选、不选、反选
//全选、不选、反选
var aBtn=document.querySelectorAll('input');
var aCheckbox=document.querySelectorAll('#box>input');
aBtn[0].onclick=function(){
for(var i=0;i<aCheckbox.length;i++){
aCheckbox[i].checked=true;
}
}
aBtn[1].onclick=function(){
for(var i=0;i<aCheckbox.length;i++){
aCheckbox[i].checked=false;
}
}
aBtn[2].onclick=function(){
for(var i=0;i<aCheckbox.length;i++){
aCheckbox[i].checked=! aCheckbox[i].checked;
}
}
//ES6简写
let aBtn=document.querySelectorAll('input');
let aCheckbox=document.querySelectorAll('#box>input');
aBtn[0].onclick=()=>{
for(let i=0;i<aCheckbox.length;i++){
aCheckbox[i].checked=true;
}
}
aBtn[1].onclick=()=>{
for(let i=0;i<aCheckbox.length;i++){
aCheckbox[i].checked=false;
}
}
aBtn[2].onclick=()=>{
for(let i=0;i<aCheckbox.length;i++){
aCheckbox[i].checked=! aCheckbox[i].checked;
}
}
选项卡
<input type="button" value="按钮1" class="active"/>
<input type="button" value="按钮2" />
<input type="button" value="按钮3" />
<div style="display: block;">1</div>
<div>2</div>
<div>3</div>
var aInput=document.querySelectorAll("input"),
aDiv=document.querySelectorAll("div")
for(var i=0;i<aInput.length;i++){
aInput[i].index=i;
aInput[i].onclick=function(){
for(var j=0;j<aDiv.length;j++){
aInput[j].className=""
aDiv[j].style.display="none"
}
this.className="active";
aDiv[this.index].style.display="block"
}
}
//闭包方式
for(var i=0;i<aInput.length;i++){
aInput[i].onclick=(function(j){
return function(){
for(var k=0;k<aDiv.length;k++){
aInput[k].className=""
aDiv[k].style.display="none"
}
this.className="active";
aDiv[j].style.display="block"
}
})(i)
}
//let+箭头函数修改
for(let i=0;i<aInput.length;i++){
aInput[i].onclick=()=>{
for(let j=0;j<aDiv.length;j++){
aInput[j].className=""
aDiv[j].style.display="none"
}
aInput[i].className="active";
aDiv[i].style.display="block"
}
}
//foreach修改
aInput.forEach((curEle,index,curArr)=>{
curEle.onclick=()=>{ //当前按钮绑定点击事件 三个参数(当前按钮,index,当前数组(整个数组的集合))
aInput.forEach((cur,i,arr)=>{
cur.className="";
aDiv[i].style.display="none"
})
curEle.className="active";
aDiv[index].style.display="block"
}
})
隔行变色
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
var aDiv=document.querySelectorAll("div");
var oldColor=null;
for(var i=0;i<aDiv.length;i++){
if(i%2==0){
aDiv[i].className="even";
}else{
aDiv[i].className="odd";
}
aDiv[i].onmouseover=function(){
oldColor=this.className; //改变class前,先记住原来的颜色
this.className='active'
}
aDiv[i].onmouseout=function(){
this.className=oldColor;
}
}
//es6简化
for(let i=0;i<aDiv.length;i++){
if(i%2==0){
aDiv[i].className="even";
}else{
aDiv[i].className="odd";
}
aDiv[i].onmouseover=()=>{
oldColor=aDiv[i].className;
// this.className='active' this指的是window
aDiv[i].className='active'
}
aDiv[i].onmouseout=()=>{
aDiv[i].className=oldColor;
}
}
6、call、apply、bind
function show(a,b){
console.log(this,a,b)
}
show.call("abc",10,20); //”abc“ 10 20
show.call(undefined,10,20); //window 10 20
show.call(null,10,20); //window 10 20
show.call("",10,20); //" " 10 20
show.apply("abc",[10,20]); //”abc“ 10 20
show.apply(undefined,[10,20]); //window 10 20
show.apply(null,[10,20]); //window 10 20
show.apply("",[10,20]); //" " 10 20
bind绑定:
fun.bind(this,arg1,arg2,...)
bind()方法返回值为新的函数,称为绑定函数
该方法可传入两个参数:
1, 第一个参数为this的指向
2, 第二个及以后的参数则作为函数的参数调用
//bind用法
var a=100
var obj={
a:10,
show:function(){
console.log(this.a)
}
}
//obj.show(); //10
//var fn=obj.show;
//fn() //100 在全局下调用 this指向window
var fn=obj.show;
var fn2=fn.bind(obj);
fn2(); //this指向obj 返回新的函数
//注意:fn和fn2是不相等的 bind返回值是一个新的函数
console.log(fn2===fn);//false 函数是引用类型,比较的是地址
//bind传参
function show(){
return Array.prototype.slice.call(arguments)
}
console.log(show(10,20,30)); //[10, 20, 30]
var fn2=show.bind(undefined,10); //bind undefined this指向window
console.log(fn2()); //[10]
console.log(fn2(100,200,[30])); //[10, 100, 200, Array(1)] 注意强行绑定不会消失,前面已经绑定了,后面再绑定,前面的也不会消失
//bind中this指向容易踩的坑
function User(name){
this.uName=name
}
User.prototype.show=function(){
//setTimeout(this.getName,1000) //undefined setTimeout里面的那个this指的是window
setTimeout(this.getName.bind(this),1000)//aaa this指的是new User('aaa')这个对象
}
User.prototype.getName=function(){
console.log(this.uName)
}
new User('aaa').show()
注意:setInterval(setTimeout)里面的this指向window,所以要bind改变this指向