ES6入门知识讲解

一、let和const

1、let

  1. let声明的变量只在其所在代码块有效(for循环里面使用let声明变量比较好)
var a = [];
for(var i=0;i<10;i++){
    a[i] = function(){
        console.log(i)
    }
}
a[6]();//10
上面是var声明的,全局有效,每次循环都会覆盖上一次,最后输出的就是最后一轮的i值
var a = [];
for(let i=0;i<10;i++){
    a[i] = function(){
        console.log(i)
    }
}
a[6]();//6
let声明的i,只在本轮循环中有效,每次声明的其实都是一个新的变量,最后输出6
  1. 不存在变量提升(var要是先使用后声明的话也不会报错,原因是变量提升,先声明了一个变量,不赋值)
console.log(foo);//ReferenceError
let foo = 3;
  1. 暂时性死区 只要块级作用域内存在let命令,他声明的变量就是绑定在这个区域,不再受外部影响;ES6规定,如果区域存在let和const命令,则这个区块对这些命令声明饿变量从一开始就形成封闭作用域,只要在声明之前使用这些变量都会报错
var tmp = 123;
if(true){
    tmp = 'abc';//ReferenceError
    let tmp;
}

总之,在代码块内,使用let声明变量之前,该变量都是不可使用的,在语法上成为“暂时性死区”;
4. 不允许重复声明

2、块级作用域

  1. let为JavaScript新增了块级作用;
  2. 在块级作用域中外层作用域是无法读取内层作用域的变量的;
  3. 内层作用域可以定义外层作用域同名变量;
  4. 函数本身的作用域在其所在的块级作用域之内;
  5. 块级作用域外部无法调用块级作用域内部定义的函数
{
    let a = 'test';
    function f(){
        return a;
    }
    f();//test
}
f();//test
建议:
{
    let a = 'test';
    let f = function(){
        return a;
    }
    f();//test
}

3、const

  1. const用来声明常量,一旦声明,其值就不能改变;
  2. const一旦声明常量就必须立即赋值。只声明不赋值就会报错
  3. 和let命令相同:只能在所声明的块级作用域内有效
  4. const命令声明的常量也不能提升,同样存在暂时性死区,只能在声明后使用
  5. const也不能重复声明常量
var message = "test";
let age = 12;

//报错
const message = "test1";
const age = 15;
  1. const命令只是保证变量指向的地址不变,并不保证改地址的数据不变
const foo = {};
foo.prop = 123;

foo.prop;//123
  1. 跨模块常量
//const声明的常量只能在当前代码块内有效,如果想设置跨模块的常量:
//test.js模块中
export const A = 1;
export const B = 2;
调用:
1、
import Test from "./test";
console.log(Test.A);//1
2、
import {A,B} form "./test";
console.log(A);//1

二、变量的解构赋值

ES6允许按照一定的模式,从数组和对象中提取值,对变量进行赋值,这被称为 解构

1、数组的解构赋值

ES5:
var a = 1;
var b = 2;
ES6:
var [a,b] = [1,2]
以上模式匹配写法

数组嵌套解构

let [a,[[b],c]] = [1,[[2],3]];
a//1
b//2
c//3
let [head,...tail] = [1,2,3,4];
head//1
tail//[2,3,4]

如果解构不成功,变量的值就是undefined

let [a] = [];
let [b,a] = [1];
//以上两种对于a都是解构不成功

不完全解构

等号左边的模式只匹配等号右边数组的一部分,这种情况解构依然成功
let [a,[b],c] = [1,[2,3],4,5];
a//1
b//2
c//4

等号右面不是数组,直接报错

//一下都报错
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};

对于Set解构,也可以使用数组的解构赋值

let [x,y,z] = new Set(["a","b","c"]);
x //a

解构允许默认值

let [foo = true] = [];
foo //true

let [x,y='b'] = [a];
let [x,y='b'] = [a,undefined];
//以上两种输出都是 
x //a
y //b


注意:ES6内部使用严格相等运算符(===)判断一个位置是否相等,所以一个数组成员不严格等于undefined,默认值是不会生效的

let [x = 1] = [undefined];
x //1
let [x = 1] = [null];
x //null
由于null不严格等于undefined,默认值不生效

如果默认值是表达式,那么这个表达式是惰性求值的,即只有在用到时才会求值

function f(){
    console.log('haha')
}
let [x = f()] = [1];//不执行f(),因为给x赋值1了
let [x = f()] = [];//执行

默认值可以引用解构赋值的其他变量,但是该变量必须已经声明

let [x=1,y=x] = [];  //x=1;y=1;
let [x=1,y=x] = [2]; //x=2;y=2;
let [x=y,y=1] = [];  //ReferenceError

2、对象解构赋值

对象的解构与数组的解构有一个重要的不同;数组的元素是按次序排列的,变量的取之由他的位置决定;而对象的属性是没有次序的,变量必须与属性同名,才能取到正确的值

let {bar,foo} = {foo:"aaa",bar:"bbb"};
bar // bbb
foo //aaa
let {baz,foo} = {foo:"aaa",bar:"bbb"};
baz //undefined

如果变量名与属性名不一致

let {first:f, last:l} = {first:"hello", last:"bye"};
first //undefined
f //hello
last //undefined
l //bye

实际上对象解构赋值是以下形式的简写

let {bar:bar,foo:foo} = {foo:"aaa",bar:"bbb"};

也就是说对象解构赋值的内部机制,是先找到同名属性,然后在赋值给对应的变量,真正被赋值的是后者,而不是前者

注意:采用对象解构赋值时,变量的声明和赋值是一体的,对于let和const,变量不能重新声明,所以一旦赋值的变量以前声明过,就会报错

let foo;
let {foo} = {foo:"haha"};
//Uncaught SyntaxError: Identifier 'foo' has already been declared

解构嵌套对象

let {loc: {start: { line }}} = {
    loc: {
        start: {
            line:1,
            column:5
        }
    }
}
line //1
注意:只有line是变量,loc和start都是模式,不会被赋值

对象的解构也可以指定默认值,默认值生效的条件是,对象的属性严格等于undefined

let {x = 3,y = 1,z = 2} = {x: undefined,y: 6,z: null};
x //3
y //6
z //null

解构模式是嵌套的对象,而自对象的赋属性不存在,那么将会报错

let {foo:{bar}} = {baz:"aaa"};
//Cannot destructure property `bar` of 'undefined' or 'null'.
原因很简单,因为foo这时等于undefined,再取子属性就会报错;

将一个已经声明的变量用于解构赋值

//错误写法
let x;
{x} = {x:1};
//Uncaught SyntaxError: Unexpected token =
因为JavaScript引擎会将{x}理解成一个代码块,从而发生语法错误;
只有不将大括号写在首行,避免JavaScript将其解释成代码块,才能解决这个问题。
//正确写法
let x;
({x} = {x:1});

3、数值和布尔值的解构赋值

解构赋值时,若果右边是数值或者布尔值,则会先转成对象

let {toString:s} = 123;
s === Number.prototype.toString //true
let {toString:s} = true;
s === Boolean.prototype.toString //true

对于undefined和null无法转为对象,所以对他们解构赋值就会报错

let {prop:x} = undefined;
let {prop:x} = null;
//Uncaught TypeError: Cannot destructure property `prop` of 'undefined' or 'null'.

4、圆括号问题

不能使用圆括号的情况:
1. 变量声明语句中,模式不能带有圆括号

let [(a)] = [1];
let {x:(c)} = {};
let {o:({p:p})} = {o:{p:2}};
//全部报错
//Uncaught SyntaxError: Unexpected token (
  1. 函数参数中,模式不能带有圆括号
    函数参数也属于变量声明,因此不能带有圆括号。
function f([(a)]){return a;}
//Uncaught SyntaxError: Unexpected token (
  1. 不能将整个模式或嵌套模式中的一层放在圆括号中
//全部报错
({p:a}) = {p:42};
([a]) = [5];
将整个模式放在了圆括号中了,导致报错。
//报错
[({p:a}),{x:c}] = [{},{}];
将嵌套模式的一层放在圆括号中了

可以使用圆括号的情况
赋值语句的非模式部分可以使用圆括号

[(b)] = [3];//正确
({p:(d)} = {});//正确

5、解构用途

  1. 交换变量的值
[x,y] = [y,x]
  1. 从函数返回多个值
  2. 函数参数的定义
//参数是一组有序的值
function f([x,y,z]) {...};
f([1,2,3]);
//参数是一组无序的值
function f({x,y,z}) {...};
f({z:3,x:1,y:2});
  1. 提取JSON数据
  2. 函数参数的默认值
  3. 遍历map解构
  4. 输入模块的指定方法

三、字符串的扩展

1、字符串扩展方法

传统上,JavaScript中只有indexOf方法可以来确定一个字符串是否包含在另一个字符串中;
ES6新增三种:
- includes():返回布尔值表示是否找到了参数字符串
- startsWith():返回布尔值,表示参数字符串是否在源字符串的头部
- endsWith():返回布尔值,表示参数字符串是否在源字符串的尾部

这三个方法都支持第二个参数 表示开始搜索的位置

let t = "hello world";
t.includes("e",4);//false

2、repeat()

repeat方法返回一个新的字符串,表示将原字符串重复n次。

"hello".repeat(3); //hellohellohello
"hello".repeat(0); //""

如果是小数,会取整

"hello".repeat(2.7); //hellohello

如果是负数或者Infinity,会报错

"hello".repeat(-2);//Uncaught RangeError: Invalid count value
"hello".repeat(Infinity); //Uncaught RangeError: Invalid count value

如果是0到-1之间的小数,则等同于0,因为先进行取整计算,0到-1取整是-0,repeat视为0

"hello".repeat(-0.8); //""
参数NaN等同于0
"hello".repeat(NaN); //""

如果repeat参数是字符串,则会先转换成数字

"hello".repeat("he"); //""
"hello".repeat("2"); //"hellohello"

3、字符串补全

padStart用于头部补全
padEnd用于尾部补全

x.padStart(5,"ab");//ababx
x.padStart(4,"ab");//abax

x.padEnd(5,"ab");//xabab
x.padEnd(4,"ab");//xaba

第一个参数指定字符串长度,第二个参数是用来补全的字符串

如果源字符串长度大于指定的最小长度,则返回源字符串

xxx.padEnd(2,"ab");//xxx

如果第二个参数省略,则用空格补全

x.padEnd(3);//'  x'
x.padEnd(3);//'x  '

4、模版字符串

模版字符串是增强版的字符串,用反引号(`)标识;他可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量

let name="Tom",time="today";
`hello ${name},how arw your ${time}`

大括号里面可以放任意的JavaScript表达式,可以进行运算,以及引用对象属性。

let x = 1;
let y = 2;
`${x}+${y}=${x+y}`//1+2=3

let obj = {x:1,y:3};
`${obj.x+obj.y}`
// 4

模版字符串中还能调用函数

function fn(){
    return "hehe";
}
`test ${fn()}`
// test hehe

如果模版字符串中的变量没有声明,会报错

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值