ES6学习笔记(一)

最近学习了ES6,被它更简洁的代码编写方式、面向对象以及模块化开发所吸引。ES6有一定的学习成本而且知识点比较琐碎,我把自己经常用到的知识点进行了整理。

安装与配置

es6很强大,遗憾的是所有浏览器都没有完美支持它。因此我们需要通过babel将es6转换成es5让我们的代码在浏览器端运行。

我本人用的是webpack+babel,你也可以使用gulp或者直接将babel的browser.js引入,将type设为"text/babel"。

首先安装webpack

npm install webpack --save-dev 

webpack需要安装相应的loader加载器—babel-loader,别忘了安装转换规则—babel-preset-es2015

npm install babel-loader --save-dev
npm install babel-preset-es2015 --save-dev

接下来简单地配置一下webpack.config.js文件

module.exports = {
  entry: "./main.js",
  output: {
    path: __dirname,
    filename: "after.js"
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        loader: 'babel-loader',
        query: {
          presets: ['es2015']
        }
      }
    ]
  },
}

上面的main.js就是我们即将要写的es6代码,通过在命令行输入webpack将其转化成es5并保存在after.js中,因此我们只需要引入after.js即可。如果你希望webpack可以实时监听并编译,可以安装webpack-dev-server,这里不多说明。

小贴士:如果你在使用es6中的Generator、async的时候遇到了错误信息regeneratorRuntime is not defined,请单独安装babel-polyfill:在webpack.config.js的头部var babelpolyfill = require("babel-polyfill");,将入口文件改写成entry:["babel-polyfill","./main.js"],,然后在你的js中import "babel-polyfill"

准备工作已经完成,接下来我们可以测试一下,我准备了一个用es6编写的main.js文件

class MyClass{
    constructor(x,y){
        this.x=x;
        this.y=y;
    }
    print(){
        return `(${this.x},${this.y})`;
    }
}
var myclass=new MyClass(2,3);
console.log(myclass.print());

运行webpack后看看生成的after.js里面都有啥

//部分代码
var MyClass = function () {
        function MyClass(x, y) {
            _classCallCheck(this, MyClass);
            this.x = x;
            this.y = y;
        }
        _createClass(MyClass, [{
            key: "print",
            value: function print() {
                return "(" + this.x + "," + this.y + ")";
            }
        }]);
        return MyClass;
    }();
    var myclass = new MyClass(2, 3);
    console.log(myclass.print());

可以看到webpack已经将es6转化为es5,现在可以尽情使用es6了。

let和const

let

let是新的变量声明方式,使用方法类似于var,但是let声明的变量只在它所在的代码块内有效

{
    var name="SunnyChuan";
    let age=22;
}
console.log(name); //"SunnyChuan"
console.log(age);  //age is not defined

let变量只在自己的块级作用域内有效,也就意味着使用let可以代替闭包解决常见的for循环引用同一个变量的问题

for(let i=0;i<5;i++)console.log(i);  //0 1 2 3 4

let不存在变量声明提升,必须先声明后使用

console.log(name); //ReferenceError
let name="SunnyChuan";

let不允许在同一个作用域内重复声明同一个变量(无论新变量是let/const/var)

let name="SunnyChuan";
var name="DannyQin"; //报错

const

const是es6增加的另一个变量声明方式,它用来声明常量,并且声明后变量的值不能再更改。因此一旦声明必须初始化,不能稍后再赋值

const a=100;
a=10; //TypeError
const b  //SyntaxError;
b=100;

const和let一样存在自己的作用域,个人认为除了变量的值是否可以改变以及是否必须声明立即初始化之外,let和const没有其他区别。需要注意的是,对于对象,数组等复合型的变量,const保证的是地址不变而不是值不变

const arr=[1,2,3];
arr.push(4); //地址不变,改变值是可以的
arr=[5]; //修改了地址,报错

变量的解构赋值

es6支持解构赋值的形式将变量的赋值简单化,数组/对象/字符串/数值/布尔/函数均可解构赋值。最为常用的是数组和对象。

数组的解构赋值

只要等号两边的模式相同即可解构成功

var [a,b,c]=[1,2,3] //a=1,b=2,c=3
var [a,,b] //a=1,b=3
var [a,..b] //a=1,b=[2,3]

当左边的数量大于右边时,右边会默认用undefined进行补充,导致解构不成功

let [a,b,c]=[1,2] //a=1,b=2,c=undefined

允许指定默认值,默认值只有当左边的变量所对应的右边的值严格等于undefined才生效

var [a,b,c=3]=[1,2]; //a=1,b=2,c=3
var [a,b,c=3]=[1,2,null]; //a=1,b=2,c=null

对象的解构赋值

与数组不同的是,对象解构赋值依靠的是key值,因此只要左边和右边key值同名即可(变量名等于属性名),无所谓顺序,而数组是按照顺序赋值的

var {name,age}={name:"SunnyChuan",age:22}; //name="SunnyChuan" age=22 
//相当于
var {name:name,age:age}={name:"SunnyChuan",age:22};

按照上面的匹配方式,变量名必须等于属性名,如果不相等则匹配失败。如果变量名不等于属性名,只能使用属性名:变量名的形式,不能省去变量名。这时候,属性只不过是一个模式,真正被赋值的是变量

var {name:myName,age:myAge}={name:"SunnyChuan",age:22};
//name is not defined, age is not defined, myName="SunnyChuan", myAge=22

对象解构赋值也提供了默认值,与数组相同,只有属性值严格等于undefined时才生效

var {name,age=22}={name:"SunnyChuan"} //name="SunnyChuan" age=22
var {name,age=22}={name:"SunnyChuan",age:null} //name="SunnyChuan" age=null

解构赋值最常用的地方就是交换变量。不需要额外的临时变量temp,一句代码就搞定

[x,y]=[y,x]

字符串/数值/数组的扩展

字符串的扩展

includes(str),返回布尔值,是否在当前字符串中找到了str

"SunnyChuan".includes("Chuan"); //true

startsWith(str),返回布尔值,当前字符串是否以str开头

"SunnyChuan".startsWidth("Sunny"); //true

endsWith(str),返回布尔值,当前字符串是否以str结尾

"SunnyChuan".endsWith("Chuan"); //true

repeat(n),将当前字符串重复n次(可以理解为在原有的基础上重复n-1次)并返回新字符串,如果n是小数则向下取整。当n小于等于0时,返回空字符串

"x".repeat(3); // "xxx"

模板字符串

var name="SunnyChuan";
var str=`hello ${name},this is ES6 `;
//等同于"hello"+name+",this is ES6";

数值的扩展

Number.isFinite(n),布尔值,检查n是否有穷,与es5的isFinite()不同的是,它不会进行类型转换,因此只对真正的数值有效

Number.isFinite(10); //true
Number.isFinite(NaN); //false
Number.isFinite(Infinity); //false
Number.isFinite("10"); //false

Number.isNaN(n),布尔值,检查n是否是NaN,与es5的isNaN()不同的是,它不会进行类型转换,因此只对真正的NaN有效

Number.isNaN(NaN); //true
Number.isNaN("str"); //false

Number.isInteger(n),布尔值,检查n是否是整数,需要注意1.0和1是同一个值

Number.isInteger(1); //true
Number.isInteger(1.0); //true
Number.isInteger(1.2); //false

Math.trunc(n),去除小数部分并返回(正数向下取整,负数向上取整)

Math.trunc(1.2); //1
Math.trunc(-1.2); //-2

Math.sign(n),布尔值,n是正数返回+1,是负数返回-1,0返回0,-0返回-0,其他值返回NaN

Math.sign(100); //+1
Math.sign(-100); //-1
Math.sign(0); //0
Math.sign(-0); //-0
Math.sign("str"); //NaN

数组的扩展

Array.from(list),将list转化成真正的数组,常用于将nodeList/arguments等伪数组
转化成数组

var obj={a:1,b:2,c:3};
Array.from(obj); //[1,2,3]
var div=document.getElementsByTagName("div");
Array.from(div); //[[object HTMLDivElement],[object HTMLDivElement],[object HTMLDivElement]]

includes(n),布尔值,检查当前数组是否包含n,可以接收两个参数,第二个参数代表搜索的起始位置(负数代表从后往前)

[1,2,3,4].include(2); //true
[1,2,3,4].include(2,2); //false
[1,2,3,4].include(2,-3); //true

数组新增三种遍历方式:entries()(遍历key和value)/keys()(遍历key)/values()(遍历value)

for(let v of ["a","b","c","d"].values()){
    console.log(v);
} //"a" "b" "c" "d"

for(let k of ["a","b","c","d"].keys()){
    console.log(k);
} //0 1 2 3

for(let [k,v] of ["a","b","c","d"].entries()){
    console.log(k,v);
} //0 "a" 1 "b" 2 "c" 3 "d"

函数和对象的扩展

函数的扩展

es6支持函数的参数设置默认值,但是这些参数必须位于函数的尾部,并且参数的变量是默认声明的,因此不能用let/const再次声明

function func(x,y=5){
    console.log(y); //5
    let y=3; //error
}

扩展运算符,用于将数组(伪数组)展开成参数序列

console.log(...[1,2,3]); //1 2 3
[...document.getElementsByTagName("div")]; //[[object HTMLDivElement],[object HTMLDivElement],[object HTMLDivElement]]

扩展运算符有很多应用场景,这里列举三个

  1. 数组合并
[1,2,3].concat([4,5,6]); //es5
[1,2,3,...[4,5,6]]; //es6

2.与解构结合(用于生成数组)

let [a,b,...c]=[1,2,3,4,5]; //a=1,b=2,c=[3,4,5] 扩展运算符必须放在最后

3.Math.max的参数不支持数组,在es5中需要用到apply。用扩展运算符可以解决该问题

Math.max.apply(Math,[1,2,3]); //es5
Math.max(...[1,2,3]); //es6 相当于Math.max(1,2,3)

箭头函数,如果不需要参数则用圆括号代替参数部分,如果函数体有多行代码则用大括号括起来

var func=x=>x*2; //var func=function(x){return x*2;}
var func=()=>true; //var func=function(){return true;}
var func=(x,y)=>{var z=x+y;console.log(z);} //var func=function(x,y){var z=x+y;console.log(z);}
var func=()=>({a:1,b:2}); //返回对象需要用圆括号包起来,圆括号代表函数体,花括号代表这是一个对象

函数绑定,使用a::b的形式取代传统的bind/call/apply

a::b; //b.bind(a);
a::b(...arguments); //b.apply(a,arguments);

对象的扩展

es6允许在对象中只写key,这样默认了value等于key所代表的变量值

var [name,age]=["SunnyChuan",22];
var obj={name,age}; //obj={name:"SunnyChuan",age:22} 
//相当于obj={name:name,age:age};

对象的方法也可以简写

var obj={
    func(){
        //函数体
    }
}
//相当于
var obj={
    func:function(){
        //函数体
    }
}

Object.assign(obj,obj1,obj2,...),将obj1/obj2/...与obj进行拼接(修改obj本身)

var [obj,obj1,obj2]=[{a:1},{b:2},{c:3}];
Object.assign(obj,obj1,obj2);
console.log(obj); //{a:1,b:2,c:3}

Object.is(obj1,obj2),布尔值,判断两个值是否严格相等,与===不同的是,+0不等于-0,NaN等于NaN

Object.is(100,100); //true
Object.is(NaN,NaN); //true
Object.is(+0,-0); //false
Object.is({a:1},{a:1}); //false
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容