ES6(一)let和const、模板字符串、箭头函数、扩展运算符

ES6(一)

ECMAScript

  • 通过ECMA-261标准化的脚本程序语言

  • 第六版(ES6)是2015年发布的

let

作用跟var一样,但声明的变量有一些特性

let a;
let b,c,d;
let e = "joseph";
let f = [];

1.注意不可重复声明,会报错,

let name = "joseph"
let name = "Joseph"
//报错
//是为了防止污染变量

2.块级作用域

全局,函数,eval(es5严格模式)

//①内层变量覆盖外层变量的情况
var tmp = new Date();
function f(){
	console.log(tmp);
    if(false){
		var tmp = "hello world"
    }
}
f() // 控制台输出undefined

//②用于计数的循环变量泄露为全局变量
var s = "hello";
for(var i = 0 ; i < s.length ; i++){
	console.log(s[i])
};
console.log(i); //5

例如if else while for里面的花括号和函数里面,let声明的变量只在这里面有效

3.不存在变量提升(练习JS笔记(二)中的预编译过程)

console.log(a);
var a = "Joseph"
//这里用的var,在执行第一行时,GO对象中的a是undefined

console.log(a);
let a = "Joseph"
//Error:Cannot access "a" before initalization

4.不影响作用域链

{
	let name = "Joseph"
	function fn(){
		console.log(name);
	}
	fn();
}
//在上一级作用域中找到了let

5.暂时性死区(TDZ)

  • 只要在块级作用域内存在 letconst命令,它所声明的变量就绑定了这个区域,不再受外部的影响,即不会沿着作用域链找上面的同名变量(所以在 let 之前使用该变量会报错)
var tmp = 123;

if(true){
    //TDZ开始
    tmp = 'abc';	//饱错
    console.log(tmp); //报错
    
    let tmp; //TDZ结束
    console.log(tmp) //undefined
    
    tmp = 123;
    console.log(tmp); //123   
}

//比较隐蔽的死区
function bar(x=y,y=2){
    return[x,y];
}
bar();
//这里调用函数会报错
//因为相当于let x = y;let y = 2;
//在声明x的时候y位于暂时性死区

一些实例

for(var i = 0 ; i < 3 ; i++){
	items[i].onclick = function(){
		this.style.background = "pink";
	}
}
//这里能实现点击盒子变成粉色

for(var i = 0 ; i < 3 ; i++){
	items[i].onclick = function(){
		items[i].style.background = "pink";
	}
//这里无法实现,因为闭包的问题,怎么点都是第三个盒子变色。
}

for(let i = 0 ; i < 3 ; i++){
	items[i].onclick = function(){
		items[i].style.background = "pink";
	}
//这里能够实现,因为每次的i都是在自己的代码块中有效,互不影响
}

const(定义常量)

  1. 一定要赋初始值,否则报错
  2. 一般常量使用大写(一般规则)
  3. 常量的值不能修改
  4. 也是块级的作用域
  5. 对于数组和对象的元素修改,不算做对常量的修改,不会报错(实质是因为指向地址)
const TEAM = ['A','B','C'];
TEAM.push('D');
//数组元素被加进去了,但是TEAM指向的地址没有变化,所以不报错
TEAM = 100//这里就会报错了

变量结构赋值

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

基本用法


let [head,...tail] = [1,2,3,4];
head;//1
tail;//[2,3,4]
//这里利用了扩展运算符
  • 以下是解构不成功的情况
let [foo] = [];
let [bar,foo] = [1];
//两种情况得到的foo都是undefined

默认值

let [x , y ='b'] = ['a'];
//x='a',y='b'

let [x , y ='b'] = ['a' , undefined];
//x='a',y='b'
//ES6内部使用严格相等运算符(===)判断一个位置是否有值。如果不严格等于undefined,默认值是不会生效的

对象的解构赋值

与数组的不同点:数组的元素是按次序排序的,变量的取值是由它的位置决定的;而对象的属性没有次序,变量必须与属性同名才能取到正确的值。

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

注意:对象的解构赋值的内部机制是先找到同名属性,然后再赋值给对应的变量,真正被赋值的是后者,而不是前者。

let {foo:baz} = {foo:"aaa",bar:"bbb"};
baz //"aaa"
foo //error: foo is not defined

//上面的代码,foo是匹配的模式,baz才是变量。

也可以用于嵌套结构的对象

let obj = {
	p:['Hello',{y:'World'}]  
}
let { p:[x,{y}] } = obj;
x //"Hello"
y //"World"

//注意这里的p是模式,不是变量,因此不会被赋值
//对象解构赋值的实质
let { p } = obj的实质如下
let { p : p } = obj;

匹配模式

var node = {
	loc:{
		start:{
			line:1,
			column:5
		}
	}
}

var { loc, loc:{start}, loc:{ start: {line} } }
loc //Object{start:Object}
start //Object{line:1, column:5}
line	//1
//最后一次对line属性的解构赋值中,只有line是变量,loc和start是匹配模式
  • 由于数组本质是特殊的对象,因此我们可以对数组进行对象属性的解构
let arr = [1,2,3];
lat { 0:first , [arr.length-1]:last } = arr;
first	// 1
last	// 3

字符串的解构赋值

  • 本质:字符串是一个类数组的对象
const [a,b,c,d,e] = "hello"
a // "h"
d // "l"
e // "o"

let { length : len } = "hello";
len // 5

数值和布尔值的解构赋值

  • 解构赋值时,如果等号右边时数值和布尔值,会把他们先转为对象(即Number.prototype或Boolean.prototype)
let { toString:s } = 123;
s === Number.prototype.toString // true

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

注意:等号右边是纯undefined或null(会报错,区别默认值)

用途

交换变量的值
let x = 1 ;
let y = 2 ;
[x, y] = [y, x];
从函数返回多个值
function example(){
	return [1,2,3];
}
let [a,b,c] = example();
//数组

function example(){
	return{
		foo:1,
		bar:2
	}
}
let {foo,bar} = example();
提取JSON数据
let jsonData = {
	id:42,
	status:"ok",
	data:[867,53902]
}
let {id,status,data:number} = jsonData
函数参数的默认值
jQuery.ajax = function(url , {
	async = true,
	beforeSend = function(){},
	cache = true,
	complete = function(){} ,
	global = true;
}){
	...
}

模板字符串(反引号)

  • ES6 引入了新的声明字符串的方式 [``]这里是反引号 ‘’ “”
let str = `反引号内也是字符串`;
console.log(str,typeof str);
//得到 反引号内也是字符串 string 
  • 特性(与普通引号区别)

    • 内容中可以出现换行符
    let str = `<ul>
    			<li>乔治夫</li>
    			<li>冥叶</li>
    			<li>Joseph</li>
    		</ul>`;
    //在普通单引号双引号下以上的形式会报错,除非每个标签套引号,然后相加
    
    //但是在反引号中内容可以直接进行换行缩进操作,合法的
    
    
    • 进行变量的拼接
    let name = 'joseph';
    let out = `${name}要不断前进才能变强`;
    console.log(out);
    // 这里能成功拼接,以前的方法是通过"+"实现字符串拼接
    

简化对象写法

  • ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。简洁书写
let name = 'Joseph';
let study = function(){
	console.log('学习upupup!');
}

const me = {
	name,
	study,
	//还可以简化加入新方法的步骤
	sleep(){
		console.log("该睡觉了");
	}
}
console.log(me);
//得到对象中符合 name : "Joseph",study : f(),sleep : f()   __proto__:Object

函数参数赋初始值

function (a,b,c){
	return a+b+c;
}
let result = add(1,2)
//控制台输入result 得到NaN,不是一个数


//注意:具有默认值的参数,一般位置要靠后面
function (a,b,c=10){
	return a+b+c;
}
let result = add(1,2)
//这里得到13

function (a,c=10,b){
	return a+b+c;
}
let result = add(1,2)
//得到NaN,2赋值给了c
  • 配合解构赋值
function connect(options){
	//let host = options.host;
	//let username = options.username;
	//let password = options.password;
	//let port = options.port;
	//以上是传统方法
    
    //利用解构
    let {host,username,password,port} = options

}
connect({
	host : 'localhost',
	username : 'root',
	password : 'root',
	port : 8000
});

    //在下面我们利用参数可赋值的特性
function connect({host="127.0.0.1",username,password,port}){
	console.log(host);
    //如果host没有传就走默认值,传了就用传的localhost
}
connect({
	host : 'localhost',
	username : 'root',
	password : 'root',
	port : 8000
});

rest参数

  • ES6中引入rest参数,用于获取函数的多余的实参,这样就不需要使用arguments对象了。rest参数搭配的变量是一个数组,该变量将多余的参数放入其中

写法 “function(…变量名){}”,然后这个变量会成为一个函数中的数组

function data(){
	console.log(arguments);
	//这里得到类数组(对象),他的_proto_是Object.prototype
	// "0" : 'Joseph'....(联系JS笔记五中的类数组),他的原型是对象
    //所以不能用数组的push方法,除非自己定义
    // "push" : Array.prototype.push
}
data('Joseph','冥叶','乔治夫');

//前面三个点是必要的,表示是rest参数
function data(...args){
    console.log(args);
    //它的_proto_是Array.prototype
    //这里得到的args就是真正的数组了,可以直接使用push方法
}
data('Joseph','冥叶','乔治夫');

function data(a,b,...args){
    console.log(args);
	//得到[3,4,5,6]
    //如果...args放中间会报错
}
data(1,2,3,4,5,6);

扩展运算符

  • 将数组转换为逗号分隔的参数序列(相当于rest参数的逆运算)
//声明一个数组
const names = ['Joseph','冥叶','乔治夫'];

//声明一个函数
function out(){
    console.log(arguments);
}
out(...names);//相当于传输了一个参数序列 传进去了三个用逗号分隔的参数

该运算符多用于函数调用

function push(array,...items){
	array.push(...items);
	return array
}

function add(x,y){
	return x + y;
}
var numbers = [4,52];
add(...numbers);//得到56
  • 实例

    • 数组合并
    //常规方法:利用数组中的concat方法
    const cp1 = ['琴子','九郎'];
    const cp2 = ['金木','董香'];
    const cmp = cp1.concat(cp2);
    //以上是常规方法
    
    //现在我们利用扩展运算符
    const cmp = [...cp1,...cp2];
    //得到一个含四个人的数组
    
    • 数组克隆
    const cp1 = ['琴子','九郎'];
    const new = [...cp1];
    //当然如果里面是引用值,这里做的只是浅拷贝
    
    • 将类(伪)数组转化为真正数组
    //假设body中有三个div
    const divs = document.querySelectorAll('div');
    //这里的divs是个类数组
    //下面是转化为真正的数组,可以用数组的方法,不过一般都是用rest,
    divArr = [...divs];
    

箭头函数以及声明特点

  • ES6 允许使用 箭头(=>)定义函数
//以前
let fn = function(){

}

//现在
let fn = (a,b)=>{
	return a + b;
}
let c = fn(1,2);

  • 区别

    1. this是静态的,this始终指向==函数声明时所在AO作用域下(并非自身函数)==的this(即call,apply都不会改变)
    function getName(){
        console.log(this.name);
    }
    let getName2 = ()=>{
        console.log(this.name)
    }
    
    //设置window对象上的name属性
    window.name = 'Joseph';
    const obj = {
        name : "Koseph"
    }
    
    
    //利用call改变函数内部this的指向
    getName.call(obj);
    getName2.call(obj);
    //第一个改变了getName中的this指向
    //第二个仍然是 'Joseph'
    
    1. 不能作为构造函数实例化对象
    let Person = (name,age) => {
    	this.name = name;
    	this.age = age;
    }
    let me =new Person("J","30");
    console.log(me);
    //会报错
    
    1. 不能使用 arguments 变量
    let fn = () => {
    	console.log(arguments);
    }
    fn(1,2,3);
    // 如果是let改为var 得到就是[1,2,3];
    // 这里报错
    
    1. 箭头函数的简写
    //1.省略小括号,当只有一个实参的时候
    let add = n =>{
        return n + n;
    }
    console.log(add(3));
    //得到6
    
    //2.省略花括号,当代码体只有一个语句的时候,此时return也要省略
    //而且语句的执行结果就是函数的返回值
    let pow = n => n*n;
    console.log(pow(9))//得到81
    
  • 实例应用(点击盒子2s后变成粉色)

let ad = document.getElementById("box");
ad.addEventListener("click",function(){
	setTimeout(function(){
        //因为setTimeout是属于window上面的方法
        //所以这里的this指向的是window
	this.style.background = 'pink';
	},2000)
})


//解决方法(外部保存this)
ad.addEventListener("click",function(){
    
    let _this = this;
    //这里的this指向的是ad
	setTimeout(function(){
	_this.style.background = 'pink';
	},2000)
})

//利用箭头函数的this指向的是函数声明时的作用域的特点
ad.addEventListener("click",function(){

	setTimeout(()=>{
	this.style.background = 'pink';
        //执行时这里的this指向的是作用域第1位,而不是第0位
        //第0位是window(因为setTimeout),第一位是ad
	},2000)
})

  • 返回数组中的偶数
 const arr = [1,2,3,4,5];
 const result = arr.filter(item = > item % 2 ===0);
 //filter是数组的一个方法,item是对里面元素的遍历,将元素为true的取出来
 console.log(result);
 //得到[2,4]
 

参考文献:《ES6标准入门》

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值