ECMAScript基础入门

JavaScript(浏览器端)=ECMAScript(语法+API)+DOM+BOM

es6开始let代替var声明变量(初始化后可重新赋值),而const声明常量(初始化后不可重新赋值,否则会报错)

const注意事项

  1. 使用const声明常量,一旦声明,就必须立即初始化,不能留到以后赋值
  2. const声明的常量,允许在不重新赋值的情况下修改它的值(引用数据类型)
const person={username:'Alex'};
person.username='ZhangSan';
console.log(person);    //{username:"ZhangSan"}

let、const和var区别

  • 重复声明(已经存在的变量或常量,又声明了一遍)var允许重复声明 而let const不允许
function func(a){
            let a=1;
        }
        func();

  • 变量提升(var会提升变量的声明到当前作用域的顶部 而let和const不存在变量提升)
        console.log(a);
        var a=1;
        console.log(a);
        console.log(b);
        let b=2;

  • 暂时性死区(只要作用域内存在let、const,它们所声明的变量或常量就自动绑定这个区域,不再受到外部作用域的影响) 
        let a=2;
        let b=1;
        function func(){
            console.log(b);
            console.log(a);
            let a=1;
        }
        func();

 

调用func函数,此时a b在函数作用域内,因为b没有在函数内继续声明,它就可以离开当前作用域(即函数作用域)到全局作用域寻找,寻找到全局变量b=1,所以输出,而a已经在函数内继续声明了,即使a在当前作用域找不到,它也不能离开当前作用域去寻找

  • window对象的属性和方法(全局作用域中,var声明的变量,通过function声明的函数,会自动变成window对象的属性或方法,而let const不会) 
        let age=18;
        const add=function (){};
        console.log(window.age);    //undefined
        console.log(window.add===add);  //false
  • 块级作用域(let和const有块级作用域,var没有
        for (let i = 0; i < 3; i++) {}
        console.log(i);

// 作用域链
        function func(){
            for (let i = 0; i < 3; i++) {
                console.log(i);
            }
        }
        func();
        console.log(i);

作用域链:内层作用域->外层作用域->全局作用域 

let和const的应用(点击按钮几控制台就显示几)

在没有学习es6之前,我们使用闭包处理

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        body{
            padding: 50px 0 0 150px;
        }
        .btn{
            width: 100px;
            height: 100px;
            margin-right: 20px;
            font-size: 80px;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <button class="btn">0</button>
    <button class="btn">1</button>
    <button class="btn">2</button>
    <script>
        // 闭包
        var btns=document.querySelectorAll('.btn');
        for(var i=0;i<btns.length;i++){
            (function (index){
                btns[index].addEventListener('click',function(){
                    console.log(index);
                })
            })(i);
        }
    </script>
</body>
</html>

学习es6之后,学会利用块级作用域

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        body{
            padding: 50px 0 0 150px;
        }
        .btn{
            width: 100px;
            height: 100px;
            margin-right: 20px;
            font-size: 80px;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <button class="btn">0</button>
    <button class="btn">1</button>
    <button class="btn">2</button>
    <script>
        let btns=document.querySelectorAll('.btn');
        for(let i=0;i<btns.length;i++){
            (function (index){
                btns[index].addEventListener('click',function(){
                    console.log(index);
                })
            })(i);
        }
    </script>
</body>
</html>

模板字符串 

模板字符串与一般字符串的区别:没什么区别,就是模板字符串与其他东西一起使用时,方便注入

const person={
            username:'Alex',
            age:18,
            sex:'male'
        };
        //const info='我的名字是'+person.username+',性别:'+person.sex+',今年'+person.age+'岁了';
        //console.log(info);

        // 模板字符串
        const info=`我的名字是${person.username},性别:${person.sex},今年${person.age}岁了`;
        console.log(info);

模板字符串的注意事项

  • 模板字符串中,所有的空格、换行或缩进都会被保留在输出之中
  • 输出`和\等特殊字符需要在前面多加\
  • 模板字符串的注入
const username='alex';
        const person={age:18,sex:'male'};
        const getSex=function (sex){
            return sex==='male'?'男':'女';
        }
        const info=`${username},${person.age},${getSex(person.sex)}`;
        console.log(info);

具体应用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        body {
            padding: 50px 0 0 300px;
            font-size: 22px;
        }

        ul {
            padding: 0;
        }

        p {
            margin-bottom: 10px;
        }
    </style>
</head>
<body>
<p>学生信息表</p>
<ul id="list">
    <li style="list-style: none;">信息加载中</li>
</ul>
<script>
    const students = [
        {
            username: 'Alex',
            age: 18,
            sex: 'male'
        },
        {
            username: 'ZhangSan',
            age: 28,
            sex: 'male'
        },
        {
            username: 'LiSi',
            age: 20,
            sex: 'female'
        }
    ];
    const list = document.getElementById('list');
    let html = "";
    for (let i = 0; i < students.length; i++) {
        html += `<li>我的名字是:${students[i].username},${students[i].sex},${students[i].age}</li>`;
    }
    list.innerHTML = html;
</script>
</body>
</html>

 

箭头函数 

箭头函数结构:const/let 函数名=参数 =>函数体

如何将一般函数改写为箭头函数

// 声明形式
function add(){};
// 声明形式 -> 函数表达式形式
const add=function(){};
// 函数表达式形式 -> 箭头函数
const add=()=>{};

箭头函数的注意事项

  • 单个参数可以省略圆括号(特别地,无参数或多个参数不能省略圆括号)
// 单个参数
    const add = x => {
        return x + 1
    };
    console.log(add(1));
  • 单行函数体可以同时省略{}和return
// 单行函数体
    const add = (x, y) => x + y;
    console.log(add(1, 1));
  • 单行对象(需要在花括号外面加上(),让浏览器不再认为是函数体的花括号)
// 单行对象
    /*const add=(x,y)=>{
        return {
            value:x+y
        }
    };*/
    const add=(x,y)=>({
        value:x+y
    })
    console.log(add(1,1));

this指向

  • 全局作用域this指向window
  • 一般函数(非箭头函数)中的this指向
function add(){
        console.log(this);
    }
    add();//undefined->window

非严格模式下this指向由undefined转换为window,如果加上严格模式下,就为undefined

'use strict';
    function add(){
        console.log(this);
    }
    add();//undefined
//'use strict';
    function add(){
        console.log(this);
    }
    const calc={
        add:add
    }
    calc.add();
    const adder=calc.add;    //没有()是赋值
    adder();    //调用

function Person(username){
        this.username=username;
        console.log(this);
    }
    const p=new Person('晓君');

 this指向对象p

 箭头函数没有自己的this

const calc={
        add:()=>{
            console.log(this);
        }
    };
    calc.add();//window

结合作用域来看,调用方法之后,执行语句(当前为箭头函数作用域),因为函数作用域无this,往外看 又无对象作用域 直接找到全局作用域就为window了

const calc = {
        add: function () {
            const adder = () => {
                console.log(this);
            };
            adder();
        }
    };
    calc.add();

 

箭头函数没有自己的this,这里的this是add方法的this,谁调用add方法,this就代表谁,显然是calc对象

不适用箭头函数的场景

  • 作为构造函数
  • 需要this指向调用对象的时候
  • 需要使用arguments的时候
// 1.作为构造函数
    // 箭头函数没有this
    const Person=()=>{};
    new Person();

    //2.需要this指向调用对象的时候
    document.addEventListener('click',()=>{
        console.log(this);//window
    });

    //3.需要使用arguments的时候
    // 箭头函数中没有arguments
    const add=()=>console.log(arguments);
    add();

箭头函数的应用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>箭头函数的应用</title>
    <style>
        body {
            padding: 50px 0 0 250px;
            font-size: 30px;
        }

        #btn {
            width: 100px;
            height: 100px;
            margin-right: 20px;
            font-size: 30px;
            cursor: pointer;
        }
    </style>
</head>
<body>
<button id="btn">开始</button>
<span id="result">0</span>

<script>
    const btn = document.getElementById('btn');
    const result = document.getElementById('result');

    const timer = {
        time: 0,
        start: function () {
            // this
            var that = this;
            // var self = this;
            btn.addEventListener(
                'click',
                function () {
                    setInterval(function () {
                        console.log(this);//window
                        // this.time++;
                        // result.innerHTML = this.time;
                        that.time++;
                        result.innerHTML = that.time;
                    }, 1000);
                },
                false
            );
        }
    };
    timer.start();
</script>
</body>
</html>

 

const btn = document.getElementById('btn');
    const result = document.getElementById('result');

    const timer = {
        time: 0,
        start: function () {
            // this就指向timer
            btn.addEventListener(
                'click',
                () => {
                    setInterval(() => {
                        console.log(this);
                        this.time++;
                        result.innerHTML = this.time;
                    }, 1000);
                },
                false
            );
        }
    };
    timer.start();

解构赋值

解析某一数据的结构,将我们想要的东西提取出来,赋值给变量或常量

数组的解构赋值

  • 模式(结构)匹配
  • 索引值相同的完成赋值 
// 不取的,可以直接用逗号跳过
    const [a,[,,b],c]=[1,[2,4,5],3];
    console.log(a,b,c);    //1,5,3
  • 默认值的基本用法
  • 默认值的生效条件
  • 默认值表达式
// 1.默认值的基本用法
      const [a, b] = [];
      const [a, b] = [undefined, undefined];

      const [a = 1, b = 2] = [];
      console.log(a, b);    //1,2

      // 2.默认值的生效条件
      // 只有当一个数组成员严格等于(===)undefined 时,对应的默认值才会生效
      // const [a = 1, b = 2] = [3, 0];
      // const [a = 1, b = 2] = [3, null];
      const [a = 1, b = 2] = [3];
      console.log(a, b);    //3,2

      // 3.默认值表达式
      // 如果默认值是表达式,默认值表达式是惰性求值的
      const func = () => {
          console.log('我被执行了');
          return 2;
      };
      // // const [x = func()] = [1];
      const [x = func()] = [];
      console.log(x);

数组解构赋值的应用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>箭头函数的应用</title>

</head>
<body>
<p>123</p>
<p>321</p>
<p>34567</p>
<script>
    //1.常见的类数组的解构赋值
    //arguments
    function func() {
      // console.log(arguments);
      // console.log(arguments.push);
      const [a, b] = arguments;
      console.log(a, b);
    }
    func();
    func(1, 2);

    //NodeList
    console.log(document.querySelectorAll('p'));
    const [p1, p2, p3] = document.querySelectorAll('p');
    console.log(p1, p2, p3);

    //2.函数参数的解构赋值
    const array = [1, 1];
    // const add = arr => arr[0] + arr[1];
    const add = ([x = 0, y = 0]) => x + y;
    // console.log(add(array));
    console.log(add([]));

    // [x,y]=[1,1]

    // 3.交换变量的值
    let x = 1;
    let y = 2;

    // let tmp = x;
    // x = y;
    // y = tmp;
    // console.log(x, y);

    // [x, y] = [y, x];
    [x, y] = [2, 1];
    console.log(x, y);
</script>
</body>
</html>

 

对象解构赋值 

  • 模式(结构)匹配
  • 属性名相同的完成赋值

对象解构赋值的注意事项

  • 对象解构赋值的默认值
  • 将一个已经声明的变量用于解构赋值
  • 可以取到继承的属性
// 1.默认值的生效条件
    // 对象的属性值严格等于 undefined 时,对应的默认值才会生效
    const { username = 'ZhangSan', age = 0 } = { username: 'alex' };
    console.log(username, age);

    // 2.默认值表达式
    // 如果默认值是表达式,默认值表达式是惰性求值的

    // 3.将一个已经声明的变量用于解构赋值
    // 如果将一个已经声明的变量用于对象的解构赋值,整个赋值需在圆括号中进行
    // let { x } = { x: 1 };
    // console.log(x);

    let x = 2;
    ({ x } = { x: 1 });
    // [x] = [1];
    console.log(x);

    // 4.可以取到继承的属性
    // const { a = 1} = {};

    const { toString } = {};
    console.log(toString);
    // Object.prototype
    // console.log(Object.prototype);
    console.log({});

对象解构赋值的应用

const logPersonInfo1 = user => {
        console.log(user.username, user.age);
    }
    // 1.函数参数的解构赋值
    const logPersonInfo2 = ({age = 20, username: uname}) => {
        console.log(uname, age);
    }
    logPersonInfo1({username: '张三', age: 18});
    logPersonInfo2({username: '李四', age: 18});
    logPersonInfo2({username: '赵六'});

    // 2.复杂的嵌套
    const obj = {
        x: 1,
        y: [2, 3, 4],
        z: {
            a: 5,
            b: 6
        }
    }
    const {
        //y: y,   //这里的y:甚至可以不写 直接起别名y
        y,
        y: [, yy],
        z,
        z: {
            b   //起别名给6
        }
    } = obj;
    // 第一个y:代表属性名匹配
    // 第二个y:代表属性名匹配值[2,3,4]

    console.log(yy, y);
    console.log(b, z)

 

其他数据类型的解构赋值

  • 字符串的解构赋值
  • 数值和布尔值的解构赋值 
// 1.字符串的解构赋值
    // 方式一:数组形式的解构赋值
    const [a,b,,,e]='hello';
    console.log(a,b,e);
    // 方式二:对象形式的解构赋值
    const {0:m,1:n,length}='hello';
    console.log(m,n,length);

    // 2.数值和布尔值的解构赋值
    // 先将等号右边的值转为对象
    const {i=1,toString}=123;
    console.log(i,toString);

    //const {j=2,toString}=true;
    //console.log(b,toString);

    // 3.undefined和null的解构赋值
    // 由于undefined和null无法转为对象,所以对他们进行解构赋值,都会报错
    //const {toString}=undefined;

 

对象字面量

// 1.什么是对象字面量
    // 实例化构造函数生成对象
    /*const person=new Object();
    person.age=18;
    person.speak=function (){};*/

    // 对象字面量 (常用)
    /*var person={
        age:18,
        speak:function (){}
    };*/

    // 2.属性的简洁表示法
    // 属性名(默认是字符串形式的,单引号可以省略)
    // const age=18;
    // const person={
    //     // 'age':age
    //     // 当键名和变量名或者常量名一样时,可以只写一个
    //     age
    // }
    // console.log(person);

    // 3.方法的简洁表示法
    const person={
        // speak:function (){}
        // 方法可以省略冒号和function关键字
        speak(){}
    };
    console.log(person);

方括号语法

  • 方括号语法可以写在对象字面量中
// 1.方括号语法用法
    const prop='age';
    // const person={};
    // person[prop]=18;
    const person={
        [prop]:18
    }
    console.log(person);
  • 方括号可以放什么[ 值或通过计算可以得到值的(表达式)] 
// 2.方括号中可以放什么
    // 值或通过计算可以得到值的表达式
    const prop='age';
    const func=()=>'name';
    const person={
        [prop]:18,
        [func()]:'张三',
        ['sex']:'男',
        ['s'+'chool']:'广州大学'
    };
    console.log(person);

  • 方括号和点语法区别(点语法是特殊形式,当属性名由数字、字母、下划线以及$构成,并且数字还不能开头时,可以使用点语法)
  • 合法标识符可以用来作为变量或常量名
  • 当你的属性或方法名为合法标识符时,可以使用点语法,其他情况使用方括号语法

函数参数的默认值 

// 函数参数默认值基本用法
    // const multiply=(x,y)=>{
    //     if (typeof y==='undefined'){
    //         y=1;
    //     }
    //     return x*y;
    // }
    // multiply(2);

    const multiply = (x, y = 1) => x * y;
    multiply(2);    //2

函数参数默认值注意事项

  • 默认值生效条件(不传参数或者明确传递undefined作为参数)
  • 默认值是表达式,默认值表达式是惰性求值的
  • 设置默认值小技巧(函数参数默认值,最好从参数右边开始设置)

函数参数默认值的应用

// 1.接收很多参数的时候
    const logUser1=(username='zhangsan',age=0,sex='male')=>console.log(username,age,sex);
    logUser1('jessica',18,'female');
    logUser1();

    // 2.接收一个对象作为参数
    const logUser2=options=>console.log(options.username,options.age,options.sex);
    logUser2({
        username:'lisi',
        age:20,
        sex:'male'
    });

    // 3.解构赋值
    const logUser3=({username='赵六',age=0,sex='女'})=>console.log(username,age,sex);
    logUser3({
        username:'wangwu',
        age:20,
        sex:'male'
    });
    logUser3({username:'karry'});
    // 利用解构赋值默认值
    // {username='赵六',age=0,sex='女'}={username:'karry'}
    logUser3({});
    logUser3();

logUser3()等同于logUser3(undefined)

// 利用解构赋值
{username='赵六',age=0,sex='女'}=undefined
    // 利用函数参数默认值
    // const logUser3=(options={})=>console.log(username,age,sex);
    const logUser3=({username='赵六',age=0,sex='女'}={})=>console.log(username,age,sex);
    logUser3();

 

解释说明:调用logUser3()方法无传参相当于传undefined参数,这时利用函数参数默认值条件,走默认值options={},即走{username='赵六',age=0,sex='女'}={},这时利用解构赋值就可以了

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值