什么是ECMAscript
javascript的组成:ECMAscript(ES6升级的部分)+dom+bom
ES6简介
ES6,是ECMAScript6.0
ES6主要为了解决ES5的先天不足,比如JavaScript里没有类的概念
ES6做的改变
- 语法方面
let
()=>{}
... - 功能方面
数组扩展
对象扩展
字符串扩展 - 扩展方面
set/map
symbol
promise
...模块化开发
维护性较高:当你引入很多个JS文件的时候,很有可能会不清楚这些JS文件之间的依赖关系,从而导致加载顺序出错。使用模块化开发之后就能避免这个问题。
相互独立:JS本身是没有命名空间的,为了减少命名冲突,经常使用对象或者闭包来减少命名冲突。对象只能减少命名冲突的概率,闭包的过多使用会造成内存泄漏。模块化开发之后,在模块内任何形式的命名都不会和其他模块的命名产生冲突,有效的解决了命名冲突的问题
代码复用:当我们想要实现某个功能的时候,如果某个模块正好有这个功能,我们就可以直接引用该模块,不必再写多余的代码,这样可以提高代码整体的效率,减少重复冗余的代码。
node对模块化的支持
-
node实现了CommonJS模块化
-
node可以支持CommonJS模块化的语法
-
浏览器不支持CommonJS的语法
-
node v13.2.0之后
-
只需要在package.json中配置:
-
-
{
"type": "module"
}
ES6之前的模块化(CommonJS,AMD,CMD)
CommonJS:
-
它通过 require 来引入模块,通过 module.exports 定义模块的输出接口。这种模块加载方案是服务器端的解决方案(同步),node完成了对它的实现
AMD
-
采用异步加载的方式来加载模块,模块的加载不影响后面语句的执行。require.js 实现了 AMD 规范。
-
对浏览器端的异步加载尤其适用,是一个浏览器端模块化开发的规范。
CMD
和 AMD 方案都是为了解决异步模块加载的问题,sea.js 实现了 CMD 规范。
ES6模块化和CommonJS的区别
CommonJS模块输出的是一个值的拷贝,ES6模块输出的是值的引用
CommonJS模块是运行时加载,ES6模块是编译时输出接口
整体加载模块(即加载模块的所有方法),生成一个对象(_fs),然后再从这个对象上面读取方法。这种加载称为“运行时加载”,
CommonJS的模块化
//导入
let{name,age,sayHello}=require('./cjs_b');
console.log(name);//xiaoming
setTimeout(function(){
console.log(name)//xiaoming
},5000)
sayHello();//hello
//导出
var name = "xiaoming";
setTimeout(function(){
name="zhangsan"
},2000)
module.exports={
name:name,
age:12,
sayHello(){
console.log("hello")
}
}
ES6模块化
//导入
import * as n from './es6_b.js'//as起别名
import {name,age,sayHello} form './es6_b.js'
console.log(n)//obj对象
console.log(user.default.name);//默认导出
sayHello();
get();
//导出(三种)
var name='zhangsan';
var age=12;
function sayHello(){
console.log('hello')
}
export{name,age,sayHello}//统一导出
export function get(){
console.log("get")
}//分别导出
export default{
name:'zhangsan',
age:12,
sayHello(){}
}//默认导出(有一些封装的文件,默认只导出一个对象,可以使用默认导出的方式去实现)
//一个文件仅能有一个默认导出
//默认导出 工具导出模块都是这么封装的
export default = {
stringify(obj){
console.log(obj)
}
valueOf(obj){
console.log(obj)
}
}
//导入(默认)
import qs from './b.js'
console.log(qs.stringify)//[Function: stringify]
console.log(qs)//{ stringify: [Function: stringify], valueOf: [Function: valueOf] }
Babel
Babel是一个广泛使用的ES6转换器,使用babel可以将ES6代码转为ES5代码,从而在老版本的浏览器执行。这意味着,可以用 ES6 的方式编写程序,又不用担心现有环境是否支持。
1.初始化项目
npm init
2.安装babel-cli工具
npm i -g babel-cli
3.安装转换规则
-
babel-preset-es2015/2016/2017/2018...
-
babel-preset-env //永不过时的规则
-
babel-preset-latest //最新的规则
npm i -D babel-preset-env
4.配置.babelrc文件
{
"presets": [
"env"
]
}
5.进行转换
-
转化文件 babel test.js -o new_test.js
-
转化目录 babel js -d dist
6.打包(browserify)
npx browserify dist/index.js -o dist/app.js
7.垫片(babel-polyfill)
Babel 默认只转换新的 JavaScript 句法(syntax),而不转换新的 API,比如Iterator、Generator、Set、Map、Proxy、Reflect、Symbol、Promise等全局对象,以及一些定义在全局对象上的方法(比如Object.assign)都不会转码。
举例来说,ES6 在Array对象上新增了Array.from方法。Babel 就不会转码这个方法。如果想让这个方法运行,可以使用core-js和regenerator-runtime(后者提供generator函数的转码),为当前环境提供一个垫片。
yarn add core-js
import core-js
var arr = [1,2,3];
var set = new Set(arr)
console.log(set);
包管理器
NPM 是 Node.js 标准的软件包管理器
cnpm 是 npm 的一个替代选择,yarn 也是 npm 的一个替代选择。
方案一:修改npm仓库地址为淘宝仓库地址
# 修改npm下载的仓库地址
$ npm config set registry http://registry.npm.taobao.org/
# 改回原来的地址
$ npm config set registry https://registry.npmjs.org/
# 查看是否修改成功
$ npm config get registry
方案二:安装cnpm
$ npm install -g cnpm
方案三:安装yarn
$ npm install -g yarn
npm依赖安装方式
//本地安装 安装到当前文件夹
$ npm install <module_name>
//带-g的为全局安装 全局使用(所有项目通用)一般为工具
$ npm install -g <module_name>
//生产依赖 需要发布到生产环境的软件或插件(发布)
$ npm install -S <module_name>
//开发依赖 里面的插件只用于开发环境,不用于生产环境.上线就没了
$ npm install -D <module_name>
//更新依赖
$ npm update <module_name>
//卸载依赖
$ npm uninstall <module_name>
cnpm依赖安装方式
//与npm的使用方式基本一致,只是前面的关键词为cnpm
$ cnpm install -g <module_name>
$ cnpm init
yarn依赖安装方式
//语法有变化
//安装
npm install -g yarn
//初始化项目
$ yarn init
//生产依赖
$ yarn add <module_name>
//开发依赖
$ yarn add <module_name> --dev
//更新依赖
$ yarn update <module_name>
//删除依赖
$ yarn remove <module_name>
常用模块补充
添加path,url,qs
yarn add path
yarn add url
yarn add qs
使用:
//path
path.basename() //该方法返回一个参数路径的最后一部分
path.dirname() //该方法返回一个 path 的路径部分
path.extname() //该方法返回 path 的扩展名
//qs
qs.stringify()
//url
url.parse() //将一个url地址转换为一个解析对象
import qs from 'qs'
import path from 'path'
import url from 'url'
var obj={
name:'zhangsan',
age:10
}
var obj_str = qs.stringify(obj)//name=zhangsan&&age=10 对象转查询字符串
console.log(obj_str)
var p = "E:/仓库/js_day10/1.js"
var file_name = path.basename(p)//该方法返回一个参数路径的最后一部分 1.js
console.log(file_name)
var p_name = path.dirname(p)//返回一个 path 的路径部分 E:/仓库/js_day10
console.log(p_name)
var ext_name = path.extname(p)//该方法返回 path 的扩展名 .js
console.log(ext_name)
var u = "http://www.baidu.com:8080/login.php?username=zhangsan"
var obj = url.parse(u);
console.log(obj)//Url {
//protocol: 'http:',
//slashes: true,
//auth: null,
//host: 'www.baidu.com:8080',
//port: '8080',
//hostname: 'www.baidu.com',
//hash: null,
//search: '?username=zhangsan',
//query: 'username=zhangsan',
//pathname: '/login.php',
//path: '/login.php?username=zhangsan',
//href: 'http://www.baidu.com:8080/login.php?username=zhangsan'
//}
变量声明(let)
变量不能重复声明
不存在变量提升
块级作用域
不影响作用域链
常量声明const
-
拥有变量的特性
-
必须赋值
-
不能被修改
-
常量名大写
-
保存引用数据类型时,可以操作数据
//常量不可以被修改 引用数据类型里的成员可以被修改 const obj = { name:'lisi' } obj.name = 'zhangsan'//obj地址不变
解构
1.数组解构(传递顺序很重要)
let arr = [1,[2,3[4,[5]]]];
let [a,[b,c[d,[e]]]] = arr;
console.log(a,,b,c,d,e);//1 2 3 4 5
//完全解构
let nums = ['x','v','n','h','t'];
let [name1,name2,name3,name4,name5] = nums;
console.log(name1,name2,name3,name4,name5)//'x' 'v' 'n' 'h' 't'
//不完全解构
let [name1,name2] = nums;
console.log(name1,name2)//'x' 'v'
console.log(name6);//undefined
2.对象解构
var obj = {
name:'zhangsan',
age:12,
getName(){}
}
var arr = [1,2,obj];
var [a,b,{name}] = arr;
console.log(name);//'zhangsan'
//完全解构
var {name,age,getName} = obj;//对象解构时可以不考虑顺序
console.log(age,name,getName)//12 'zhangsan' [Function: getName]
//不完全解构
var {name} = obj;
console.log(name)//'zhangsan'
var {name1} = obj;
console.log(name1);//undefined
3.字符串解构
4.数值解构
//利用数组和对象解构字符串
var str = 'hello';
var [a,b] = str;
console.log(a,b)//'h' 'e'
var {length,toString,valueOf} = str//利用对象解构字符串对象中属性的方法
console.log(length,toString,valueOf);//8 [Function: toString] [Function: valueOf]
//利用对象解构数值类型
var num = 123456//不可以利用数组解构
var {toString,valueOf} = num;//数值类型可以利用对象进行解构,没有length属性
console.log(toString,valueOf)//[Function: toString] [Function: valueOf]
5.默认值解构
var obj = {
name:'zhangsan',
age:12,
getName(){}
}
var {name='lisi',age,getName} = obj;//传一个默认值'lisi'
console.log(name)//zhangsan 使用用户传的数据
模板字符串(``)
var arr = [1,2]
var tr = '<tr>'
tr+='<td>'+arr[0]+'</td>'
tr+='<td>'2'</td>'
tr+='</tr>'
console.log(tr)//<tr><td>1</td><td>2</td></tr>
//通过模板字符串去保存较长的字符串数据
var tr1 = `
<tr>
<td>${arr[0]}</td>
<td>2</td>
</tr>
`
console.log(tr1)
//<tr>
// <td>1</td>
// <td>2</td>
//</tr>
扩展运算符(...)
var arr = [1,2,3,4,5]
var new_arr = [...arr]//深拷贝
//合并操作
var arr1 = [...arr,6,7]
//聚合
var [a,...b] = arr;//剩下的未解构的成员保存在b中
console.log(a,b)//1,[2,3,4,5]
//在字符串中的应用类似
//在对象中的应用
var obj = {
name:'zhangsan',
age:12,
getName(){
console.log(this.name);
},
}
//扩展
var obj1 = {...obj};//对象的深拷贝
//对象的合并
var obj2 = {
...obj,
sex:'男',
sayHello(){}
}
console.log(obj2)//{
// name: 'zhangsan',
// age: 12,
// getName: [Function: getName],
// sex: '男',
// sayHello: [Function: sayHello]
//}
//聚合
var {name,...o} = obj;
console.log(o)//{ age: 12, getName: [Function: getName] }
对象简写
var name = 'zhangsan';
var age = 12;
var obj = {
name,
age,
getName(){}
}//babel会进行转换
var obj1 = {
name:name,
age:age,
getName:function(){}
}