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)
- 只要在块级作用域内存在
let
、const
命令,它所声明的变量就绑定了这个区域,不再受外部的影响,即不会沿着作用域链找上面的同名变量(所以在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(定义常量)
- 一定要赋初始值,否则报错
- 一般常量使用大写(一般规则)
- 常量的值不能修改
- 也是块级的作用域
- 对于数组和对象的元素修改,不算做对常量的修改,不会报错(实质是因为指向地址)
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);
-
区别
- 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'
- 不能作为构造函数实例化对象
let Person = (name,age) => { this.name = name; this.age = age; } let me =new Person("J","30"); console.log(me); //会报错
- 不能使用 arguments 变量
let fn = () => { console.log(arguments); } fn(1,2,3); // 如果是let改为var 得到就是[1,2,3]; // 这里报错
- 箭头函数的简写
//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标准入门》