一、let和const声明变量
1.let没有变量提升,把let放下面打印不出来,放上面可以
console.log(a);
let a=1;
2.let是一个块级作用域,花括号里面声明的变量外面找不到
console.log(b);
if(true)
{
let b=1;
}
//undefined
if(true)
{
let b=1;
}
console.log(b);
//undefined
console.log(b);
if(true)
{
var b=1;
}
//undefined
if(true)
{
var b=1;
}
console.log(b);
// 1
3.不能重复声明
let a=1;
let a=2;
console.log(a);
var会覆盖,但是let会报错,可以避免写代码的时候重复命名问题
4.const
const赋值之后,变量值就不能再修改了
const a=1;
a=2;
console.log(a);
//报错
const people={
name:'ttt'
}
people.name='hhh';
console.log(people.name);// hhh
const people={
name:'ttt'
}
people={
age=18
}
console.log(people.age);// 报错
const也能声明对象这种常量,不可以修改对象,可以修改对象里的一些属性
5.let和const相同点和不同点
相同:都不能重复声明、是块级作用域、没有变量提升
不同:const赋值之后不能修改
6.优点
(1)for循环用let比var好
var a=[];
for(var i=0;i<10;i++)
{
a[i]=function(){
return i;
}
}
console.log(a[5]());
最后输出来是个10,我悟了,学js的时候遇到过这个问题当时没搞懂,i是全局变量的意思是,如果i变了,其他地方的i都变(整个页面都是这一个i),上面这段输出的不管a[几]都是10。下面第一段i没走完就去赋值,结果正常,第二段没有变量提升所以也正常。
var a=[];
for(var i=0;i<10;i++)
{
a[i]=i;
}
console.log(a[1]);
const a=[];
for(let i=0;i<10;i++)
{
a[i]=function(){
return i;
}
}
console.log(a[1]());
for里面肯定不用const,后面++会被改
(2)不会污染全局变量
let RegExp=10;
console.log(RegExp);//10
console.log(window.RegExp);//f RegExp[]
window的对象不会被改
总结:默认情况下用const,除非你要修改再用let
二、模版字符串
var p=document.querySelector('p');
var id='hh';
const text='lilili';
div.innerHTML="
"+text+"
以前写是这样的,要拼接字符串,升级版:
var div=document.querySelector('div');
const id='hh';
const text='lilili';
div.innerHTML=`
${text}
id和text用${}包起来,这种方法类似在body写
三、函数默认值、剩余参数、扩展运算符
1.函数默认值
以前写一个加和函数的话:a b 如果没有输入得有一个默认值。
function add(a,b){
a=a||10;
b=b||20;
return a+b;
}
console.log(add());
ES6中:
function add(a=10,b=20){
return a+b;
}
console.log(add(20,30));
可以直接在()中写
function add(a,b=20){
return a+b;
}
console.log(add(20));//40?
function add(a=20,b){
return a+b;
}
console.log(add(20));//报错
老师讲的是只给一个值,像第一种a可以给到,b有值,能出结果,第二种肯定不行,但是我浏览器上第一种也不行,都是NaN
function zhi(c){
return c+5;
}
function add(a=zhi(4),b=20){
return a+b;
}
console.log(add());//29
默认值也可以用函数来写。
2.剩余参数
以前我们传参数的时候,不确定有几个参数值不是就用arguments伪数组来代替吗,如下:
let obj={
title:'算法',
name:'ttt',
age:18
}
function pick(obj){
//对象肯定得给我传进来,后面你选择了啥不一定
let result=Object.create(null);
//创建一个对象,最后这个函数得把函数返回出去
for(var i=1;i //从1开始,0是对象 { //arguments[i]是name 和age; result[arguments[i]]=obj[arguments[i]]; //arguments[i]才是里面的值 } return result; } let hh=pick(obj,'name','age'); //把obj对象中的name、age用pick方法选出来,存到hh对象中去 console.log(hh); es6中:用...具名参数指定剩余参数 function pick(obj,...keys){ //keys可以随便取 //对象肯定得给我传进来,后面你选择了啥不一定 let result=Object.create(null); for(let i=0;i //从0开始 { //keys[i]是name 和age; result[keys[i]]=obj[keys[i]]; //keys[i]才是里面的值 } return result; } let hh=pick(obj,'title','age'); //把obj对象中的name、age用pick方法选出来,存到hh对象中去 console.log(hh); 区别就是...是真数组,arguments是伪数组;obj对应let hh=pick(obj,'title','age');中的obj,所以i就从1开始了。 3.扩展运算符 剩余参数是把多个独立的合并到一个数组中去,扩展运算符就是把一个数组分割,并将各个项作为分离的参数给函数。 (1)以前我们想要获取两个数组中最大值的时候用apply let a=[1,2,3,4]; let b=[1,3,5,2]; console.log(Math.max.apply(a,b));//5 es6:不再用apply了 let b=[1,3,5,2]; console.log(Math.max(...a));//5 let b=[1,3,5,2]; let a={ c:1, ...b } console.log(a); a那里再...就不行了 四、箭头函数 1.箭头函数的语法 用=>代替之前的function。 // let arr=function(a,b){ // return a+b; // } let arr=(a,b)=>a+b //两个形参必须加() console.log(arr(10,20)); 没有参数的情况: let arr=()=>'hh' console.log(arr(10,20)); 输出是个数组的话得用()包起来 // let arr=id=>{ // return{ // id:'id', // name:'hh' // } // } let arr=id=>({ id:'id',name:'hh'}); let obj=arr(1); console.log(obj); 2.对象中的函数和箭头函数 let people={ name:'hh', eat:function(food){ console.log(this.name+'吃了'+food); }, eat2:food=>console.log(people.name+'吃了'+food), eat3:(food){ console.log(people.name+'吃了'+food); } } people.eat3('chincken'); 3.箭头函数的this指向 function的this就是看外面是谁,箭头函数的this就得往外翻两层 箭头函数没有this指向,箭头函数内部this只能通过查找作用域链来确定。 例1: let Person = { name: 'zzy', age: 18, getAge: function () { console.log(this.age); } } Person.getAge(); //18 let Person = { name: 'zzy', age: 18, getAge: () => { console.log(this.age); } } Person.getAge(); //undefined 用function的时候,this指向的就是这个函数的调用者,但是用箭头函数,this就得翻两层,第二个指向外面的外面就是window,window没有age属性。 例2: let Dj = { id: 007, drop: function () { document.addEventListener('click', function () { console.log(this); //document this.dance(); }) }, dance: function () { console.log('drop the beat'); } } Dj.drop(); //报错 这是一个dj对象,调用dj.drop,点击document之后发生事件,调用者是document,所以this指向document,而document没有dance方法 let Dj = { id: 007, drop: function () { document.addEventListener('click', () => { console.log(this); //Dj this.dance(); }) }, dance: function () { console.log('drop the beat'); } } Dj.drop(); //drop the beat 点击之后因为有箭头函数,this就得往外翻两个大括号到dj里面,有dance这个方法 let Dj = { id: 007, drop: () => { document.addEventListener('click', () => { console.log(this); //window this.dance(); }) }, dance: function () { console.log('drop the beat'); } } Dj.drop(); //报错 现在是往外翻四次,到了window 里面,没有dance方法 例3: (es5的)中bind是让newfn复制一份fn过来,这个新函数的this被bind的第一个参数指定,其余的参数将作为新函数的参数供调用时使用。所以再次调用fn还是指向window let people={ name:'hh', color:'pink' } function fn(){ console.log(this); return ()=>{ console.log(this); } } fn(); let newfn=fn.bind(people); newfn(); //Window {window: Window, self: Window, document: document, name: '', location: Location, …} {name: 'hh', color: 'pink'} 4.箭头函数的注意事项 1.箭头函数内部没有arguments了(arguments 是一个伪数组对象。代表传给一个function的参数列表。)this都指向window 了,arguments是外两层了不能用,没有外一层了。 2.箭头函数不能使用new关键字来事例化对象,function 是一个对象,但是箭头函数其实不是一个对象,是一个语法糖。 好文链接
发表评论