ES6笔记( let 、const、this、call/apply/bind)

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(j){
    			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指向

猜你喜欢

转载自blog.csdn.net/qq_14993375/article/details/79707619