var 与 let,const的区别
var
- 可以重复声明
- 无法限制修改
- 没有/忽略 块级作用域
因此,即使在块级作用域内定义的变量,在块级作用域外仍然能被访问。 这源于通过var声明的变量实际上总是在距离最近的函数内或全局作用域中注册的, 不关注块级作用域。
与var不同,
let和const是直接在最近的词法环境中定义变量
(可以是“块级作用域内、循环体内、函数内、全局环境内”)。因此,我们可以使用let和const定义块级别、函数级别、全局级别的变量
。
let : 不能重复声明,变量-可以修改,定义自身的块级作用域
const : 不能重复声明,常量-不能修改,块级作用域 。
for( let i=0;i<10;i++){ } console.log(i);//error, i is not defined
const FLAG= true;//使用const定义的全局静态变量,常使用大写表示 FLAG = false; console.log(FLAG); // ture
const 变量的特性:
const objConst = {}; objConst.name = 'imaginecode';
即:const变量只能在声明时被初始化一次,之后再也不允许将全新的值赋给const变量。但是,仍然可以修改const变量已经存在的值,只是不能重写const变量。
因为对象是引用类型的,objConst中保存的仅是对象的指针,这就意味着,const仅保证指针不发生改变,修改对象的属性不会改变对象的指针,所以是被允许的。也就是说const定义的引用类型只要指针不发生改变,其他的不论如何改变都是允许的。
函数
箭头函数——一种简写
注意,在箭头函数中,this指向的上下文环境与普通函数中的this有着显著的区别:
- 普通函数:谁调用this,this就指向谁
- 箭头函数:this在哪个环境中,this就指向谁
例如:
class Demo(){ construct(){ } handle1 =()=>{ this.handle2() } handle2 =()=> { let html =`<a href="javascript:;" class="btn2">btn2</a>`; $('body').append(html); $('.btn2').click(()=>{return this.handle1()}); //this指向Demo $('.btn2').click(function(){this.handle1()}); //undefined ,this指向 类名为btn2 的 a 标签 } }
function 去掉 ,加=>
#es5 function () { } #es6 ()=>{ }
- 如果只有一个参数,()可以省
- 如果只有一个return,return和花括号{}可以省
window.onload = function() { alert('abc); }; #es6 window.onload = ()=> { alert('abc'); };
参考
- https://segmentfault.com/a/1190000011194676#articleHeader2
- https://www.liaoxuefeng.com/wiki/1022910821149312/1031549578462080
函数的参数
- 参数的扩展/展开
- 默认参数
参数扩展
- 搜集剩余的参数(Rest Parameter),但必须是最后一个
function show(a,b,...args) { alert(a); alert(b); alert(args);//args = [3,4,5,6] } show(1,2,3,4,5,6);
展开数组
- 展开后的效果,跟直接把数组的内容写在这儿
let arr=[1,2,3]; show(...arr); //==show(1,2,3) function(a,b,c){ }
默认参数
- 可传可不传,传递就听你的,不传递就按默认的。
function show(a,b=1,c=2){//b=1,c=2默认参数 console.log(a,b,c); } show(7,8,9);//result: 7,8,9
解构赋值
在传统的js中,数组字面量 是不能出现在等于号(复制操作符)左边的。解构赋值的语法是把等于号右边数组中包含的值,分别赋值给等于号左边数组中的变量。
例如:
//数组 var [,value] = ["color","red"]; console.log(value);//"red" //对象 var person = { name:"imaginecode", age: 17 } var {name:personName,age:personAge} = person; console.log(personName);//"imaginecode" console.log(personAge);//17
简单理解,解构=“拆”
- 左右两边结构必须一样
- 右边必须是个东西
- 声明和赋值不能分开,必须在一句话里面
let arr=[1,2,3]; #解构赋值 let [a,b,c]=[1,2,3];//左右两边必须一样
let {a,b,c}={a:1,b:2,c:3};//json let [{a,b,c},[n1,n2,n3],num,str]=[{a:1,b:2},[1,2,3],1,'abc']; # 等同 let [json,arr,num,str][{a:1,b:2},[1,2,3],1,'abc']; console.log(json,arr,num,str);
数组
四个新方法
- map 映射:一个对一个
- reduce 汇总:一堆出来一个
- filter 过滤器
- forEach 循环(迭代)
map
let arr = [1,2,3]; let result = arr.map(function(item){ return item*2; }); alert(result); # 箭头函数改写 let result = arr.map(item=>item*2);
reduce
# 求和 let arr = [1,2,3,4,5,6]; let result = arr.reduce(function(tmp,item,index){ return tmp+item; //tmp:中间结果 //item:arr中的元素,index:下标 }); alert(result);
# 求平均数 let arr = [1,2,3,4,5,6]; let result = arr.reduce(function(tmp,item,index){ if(index!=arr.length-1){//不是最后一个 return tmp+item; }else {//是最后一个数 return (tmp+item)/arr.length; } }); alert(result);
filter
let arr = [1,2,3,4,5,6]; let result = filter(item=>item%3==0); alert(result);
let arr = [ {title:'a',price:10002}, {title:'b',price:999}, {title:'c',price:789}, {title:'d',price:10090}, {title:'e',price:11122}, ]; let result=arr.filter(json=>json.price>=10000); console.log(result);
forEach
let arr = [1,2,3]; arr.forEach((item,index)=。{ alert(index+':'+item); });
剩余参数与分布参数、默认参数
剩余参数
ES6去除了arguments对象,因此无法通过它读取未声明的参数。
不过,使用剩余参数(rest arguments)语法,也能表示你期待给函数传入 可变 数量 的参数。
剩余参数的语法形式是三个点后面跟一个标识符。
使用 这种语法可以定义可能会传进来的更多参数,然后把它们收集到一个数组中。
function sum(num1,num2,...nums){ var result = num1 + num2; for(let i=0,len=nums.length;i<len;i++){ console.log(nums[i]); result +=nums[i]; } } var result = sum(1,2,3,4,5,6);
剩余参数会保存在nums数组中。与原来的arguments不同,剩余参数都保存在Array的一个实例中。所以,可以使用任何数组方法 来操作它们。
分布参数
分布参数可以向函数中 传入一个数组,然后数组中的元素会映射到函数的每个参数上。
分布参数的语法形式与剩余参数的语法相同,就是在值的前面加三个点。
唯一的区别是分布参数在调用函数的时候使用,剩余参数在定义函数的时候使用。
var result = sum(...[1,2,3,4,5,6]);
默认参数
为参数指定默认值。如果调用函数时没有传入该参数,那么该参数就会使用默认值。
要为参数指定默认值,可以在参数名后面直接加上等于号和默认值。
function sum(num1,num2=0){ } sum(5);
字符串
- 多两个新方法
startsWith //以…开头
endsWith //以…结尾 - 字符串模板
两个新方法
let str= 'http://abc.com'; if(str.startsWith('http://')){ }else if(){ }
let str = 'a.txt'; if(str.endsWith('.txt'){ alert('文本文件'); })
字符串模板
1、直接把东西塞到字符串里面 ${东西}
2、可以折行
反单引号`
let a=12; let str = `a${a}c`;//str = a12c # 字符串拼接 let title = '标题'; let content = '内容'; let str = '<div>\ <h1>'+title+'</h1>\ <p>'+content+'</p>\ </div>'; #改写 let str2 = `<div> <h1>${title}</h1> <p>${content}</p> </div>`;
Map
用map替代if-else/switch
const fn = ()=> { console.log('find') } let handle = function(){} const map = new Map(); const arr = [1,3,5,7,9]; map.set(arr,fn); const getVal = (params) => { for(let value of map.entries()){ if(value[0].includes(params)) { handle = value[1] }else { console.log('not find') } } } let i = 9; getVal(i); handle()
ES6的面向对象
新旧对比
1、class关键字,构造器和类分开
2、class中直接加方法
特点
- 继承
旧版
function User(name,pass){ this.name = name; this.pass = pass; } User.prototype.showName = function() { alert(this.name); } User.prototype.showPass = function() { alert(this.pass); } var user = new User('blue','123'); user.showName(); user.showPass();
新版
class User{ constructor(name,pass){ this.name = name; this.pass = pass; } showName() { alert(this.name); } showPass() { alert(this.pass); } } var user = new User('blue','123'); user.showName(); user.showPass();
继承
class vipUser extends User{ constructor(name,pass,level){ super(name,pass); //super关键字,超类(父类) this.level = level; } showLevel(){ alert(this.level); } } var v1 = new vipUser('blue','123'); v1.showName(); v1.showPass(); v1.showLevel();
应用 React
- 组件化——class
- JSX (JSXbabelbrowser.js),JS扩展版本
class Test extends React.Component { constructor(...args) { super(...args); } render(){ return <span>123</span>; } } window.onload = function() { let oDiv = document.getElementById('div1'); ReactDOM.render( <Test></Test>, oDiv ); };
JSON
- JSON对象
JSON.stringify;
JSON.parse; - JSON简写(名字一样;方法)
let json = {a:1,b:2}; let str = 'http://abc.com?data='+encodeURIComponent(JSON.stringify(json)); //stringify字符串化
json 标准写法
1、只能用双引号
2、所有的名字都必须用引号包起来
let str = '{"a":12,"b":5,"c":"abc"}'; let json = JSON.parse(str);
简写
1、名字与值一样的时候,可保留一个
let a =1; let b =5; let json = {a:a,c:b};//等价于let json = {a,c:b};
2、方法简写
let json = { a:1, show(){ alert(this.a); } } json.show();
export/import
模块,或者称为“命名空间”或“包”,是组织javasript应用代码的重要方法。
每个模块都包含独立于其他模块的特定、独一无二的功能。
模块在其自己的顶级执行环境中运行,因而不会污染导入它的全局执行环境。默认情况下,模块中声明的所有变量、函数、类等都是该模块私有的。
对于应该向外部公开的成员,可以在前面加上export
关键字。例如:
a-module.js 写模块 module MyModule { //公开成员 export let myobject= {}; export function hello() {console.log('hello')} //隐藏成员 function nihao(){ } } b.js导入 //只导入myobject import myobject from MyModule; console.log(myobject); //导入所有公开成员 import * from MyModule; //列出要导入的成员 import {myobject,hello} from MyModule;
简言之,模块就是一种组织相关功能的手段,并且其能保护全局作用于不受污染。
参考:
https://stackoverflow.com/questions/48140375/javascript-es6-import-expects-exactly-one-argument
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/export