ES6(一):let和const、模板字符串、函数默认值、剩余参数、扩展运算符、箭头函数

一、let和const声明变量

1.let没有变量提升,把let放下面打印不出来,放上面可以

复制代码
<script>
        console.log(a);
        let a=1;
    </script>

2.let是一个块级作用域,花括号里面声明的变量外面找不到

复制代码
<script>
        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
    </script>

3.不能重复声明

复制代码
<script>
        let a=1;
        let a=2;
        console.log(a);
        
    </script>

var会覆盖,但是let会报错,可以避免写代码的时候重复命名问题

4.const

const赋值之后,变量值就不能再修改了

复制代码
<script>
        const a=1;
         a=2;
        console.log(a);
        //报错
    </script>

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好

复制代码
<script>
        var a=[];
        for(var i=0;i<10;i++)
        {
            a[i]=function(){
                return i;
            }
        }
        console.log(a[5]());
    </script>

最后输出来是个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

二、模版字符串

复制代码
<script>
        var p=document.querySelector('p');
        var id='hh';
        const text='lilili';
        div.innerHTML="<ul><li><p id="+id+">"+text+"</p></li></ul>";
    </script>

以前写是这样的,要拼接字符串,升级版:

复制代码
var div=document.querySelector('div');
        const id='hh';
        const text='lilili';
        div.innerHTML=`<ul>
            <li>
                <p id=${id}>${text}</p>
            </li>
            </ul>`;

id和text用${}包起来,这种方法类似在body写

三、函数默认值、剩余参数、扩展运算符

1.函数默认值

以前写一个加和函数的话:a b 如果没有输入得有一个默认值。

复制代码
<script>
        function add(a,b){
            a=a||10;
            b=b||20;
            return a+b;
        }
        console.log(add());
    </script>

ES6中:

复制代码
 <script>
        function add(a=10,b=20){
            return a+b;
        }
        console.log(add(20,30));
    </script>

可以直接在()中写

复制代码
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伪数组来代替吗,如下:

复制代码
<script>
        let obj={
            title:'算法',
            name:'ttt',
            age:18
        }
        function pick(obj){
            //对象肯定得给我传进来,后面你选择了啥不一定
            let result=Object.create(null);
            //创建一个对象,最后这个函数得把函数返回出去
            for(var i=1;i<arguments.length;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);
        
    </script>

es6中:用...具名参数指定剩余参数

复制代码
function pick(obj,...keys){
            //keys可以随便取
            //对象肯定得给我传进来,后面你选择了啥不一定
            let result=Object.create(null);
            for(let i=0;i<keys.length;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 是一个对象,但是箭头函数其实不是一个对象,是一个语法糖。

相关推荐
范文杰2 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪3 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪3 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy3 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom4 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom4 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom4 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom4 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom4 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试
LaoZhangAI5 小时前
2025最全GPT-4o图像生成API指南:官方接口配置+15个实用提示词【保姆级教程】
前端