JavaScript语言
变量声明
let 和 const
不要用 var, 而是用 const 和 let, 分别表示常量和变量。 不同于 var 的函数作用域,const 和 let 都是块级作用域。
const DELAY = 1000;
let count = 0;
count = count + 1;
模板字符串
模板字符串提供了另一种做字符串组合的方法。
const user = "world";
console.log(`hello${user}`); // hello world
// 多行
const content = `
Hello ${user},
greet guests.
`;
默认参数
function logActivity(activity = 'skiing') {
console.log(activity);
}
logActivity(); // skiing
箭头函数
函数的快捷写法,不需要通过 function 关键字创建函数,并且还可以省略 return 关键字。
同时,箭头函数还会继承当前上下文的 this 关键字。
比如:
[1, 2, 3].map((x) => x + 1); //[2, 3, 4]
等同于:
[1, 2, 3].map(function(x){
return x + 1;
}) // [2, 3, 4]
[1, 2, 3].map((function(x) {
return x + 1;
}).bind(this)); // [2, 3, 4]
[1, 2, 3].reduce(function(accumulator, currentValue){
accumulator.push(currentValue + 1);
return accumulator;
}, []); // [2, 3, 4]
对于reduce函数不清楚的同学可以参考阮一峰老师的reduce讲解
模块的 Import 和 Export
import 用于引入模块,export 用于导出模块。
比如:
// 引入全部
import React from "react";
// 引入部分
import { useState } from "react";
import React, { useState, useEffect } from "react";
// 引入全部并作为 github对象
import * as github from './services/github';
import App from "./02_函数式组件的refs";
// 导出默认
export default App;
// 部分导出, 需 import { App } from './file; 引入
export class App extends React.Component {} ;
ES6 对象和数组
解构赋值
解构赋值可以让我们从 Object 或 Array 里取部分数据存为变量。
// 对象
const user = { name: "kobe", age: 38 };
const { name, age } = user;
console.log(`${name}: ${age}`); // kobe: 38
// 数组
const arr = [1, 2];
const [foo, bar] = arr;
console.log(foo, bar); // 1 2
我们也可以解构传入的函数参数。
const add = (state, { payload }) => {
console.log("payload", payload); //2
return state.concat(payload);
};
add([ 1 ], { payload : 2 })
解构时还可以配alias,让代码更具有语义。
const add = (state, { payload: todo }) => {
console.log("todo", todo); // todo 2
return state.concat(todo);
};
add([1], { payload: 2 });
// 函数调用时,将从第二个实参中匹配模式为 payload 的属性,并重命名为 todo
字面量改进
这是解构的反向操作,用于重新组织一个 Object。
const name = "kobe";
const age = 38;
const user = { name, age }; // { name: 'kobe', age:38 }
定义对象方法时,还可以省去 function 关键字。
const example1 = new Vue({
el: '#example-1',
mounted(){
this.$nextTick(function () {
// Code that will run only after the
// entire view has been rendered
})
},
// 等同于
// mounted: function () {}
})
app.model({
reducers: {
add() {} // 等同于 add: function() {}
},
effects: {
*addRemote() {} // 等同于 addRemote: function*() {}
},
});
Spread Operator 展开语法
Spread Operator 即3个点 ...,有几种不同的使用方法。
可用于组装数组。
const todos = [1, 2, 3];
[...todos, 'Learn English']; // [1, 2, 3, 'Learn English']
也可用于获取数组的部分项。
const arr = ["a", "b", "c"];
const [first, ...rest] = arr;
console.log(rest); // [ 'b', 'c' ]
// With igore
const [first, , ...rest] = arr;
rest; // ['c']
还可以收集函数参数为数组
function directions(first, ...rest) {
console.log(rest);
}
directions('a', 'b', 'c'); // ['b', 'c'];
代替 apply。
function foo(x, y, z) {}
const args = [1,2,3];
// 下面两句效果相同
foo.apply(null, args);
foo(...args);
对于 Object 而言,用于组合成新的 Object 。(ES2017 stage-2 proposal)
const foo = {
a: 1,
b: 2,
};
const bar = {
b: 3,
c: 2,
};
const d = 4;
const ret = { ...foo, ...bar, d }; // { a:1, b:3, c:2, d:4 }
此外,在 JSX 中 Spread Operator 还可用于扩展 props,详见 Spread Attributes。
对象属性名表达式
JavaScript 定义对象的属性,有两种方法。
// 方法一
obj.foo = true;
// 方法二
obj['bar'] = 123;
上面代码的方法一是直接用标识符作为属性名,方法二是用表达式作为属性名,这时要将表达式放在方括号之内。
但是,如果使用字面量方式定义对象(使用大括号),在 ES5 中只能使用方法一(标识符)定义属性。
const obj = {
foo: true,
abc: 123
};
ES6 允许字面量定义对象时,用方法二(表达式)作为对象的属性名,即把表达式放在方括号内。
const propKey = "bar";
const obj = {
foo: true,
[propKey]: 123,
};
// obj : { foo: true, bar: 123 }
在react里setState函数应用如下:
我们实现点击按钮给球星投票
<script type="text/babel">
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
jordan: 0,
james: 0,
kobe: 0,
};
}
render() {
const { jordan, james, kobe } = this.state;
return (
<div>
<h2>球星列表</h2>
<ul>
<li>
<h2>乔丹:{jordan} 票</h2>
</li>
<li>
<h2>詹姆斯:{james} 票</h2>
</li>
<li>
<h2>科比:{kobe} 票</h2>
</li>
</ul>
<button onClick={this.increment.bind(this, "jordan")}>
乔丹+1
</button>
<button onClick={this.increment.bind(this, "james")}>
詹姆斯+1
</button>
<button onClick={this.increment.bind(this, "kobe")}>
科比+1
</button>
</div>
);
}
increment(startKey) {
const { jordan, james, kobe } = this.state;
const sourceMap = { jordan, james, kobe };
this.setState({ [startKey]: sourceMap[startKey] + 1 });
}
}
ReactDOM.render(<App />, document.getElementById("app"));
</script>
更多关于ES6对象的增强可以参考阮一峰老师ECMAScript 6 入门
Promises
Promise 用于更优雅的处理异步请求,比如发起异步请求:
fetch('/api/todos')
.then(res => res.json())
.then(data => ({ data }))
.catch(err => ({ err }));
定义 Promise 。
const delay = (timeout) => {
return new Promise((resolve) => {
setTimeout(resolve, timeout);
});
};
delay(1000).then((_) => {
console.log("executed");
});
更多有关Promise的详细内容请参考阮一峰老师ES6中Promise
Generators
dva 的 effects 是通过 generator 组织的。Generator 返回的是迭代器,通过 yield 关键字实现暂停功能。
这是一个典型的 dva effect,通过 yield 把异步逻辑通过同步的方式组织起来。
app.model({
namespace: 'todos',
effects: {
*addRemote({ payload: todo }, { put, call }) {
yield call(addTodo, todo);
yield put({ type: 'add', payload: todo });
},
},
});
// 先发异步请求addTodo,等到响应之后再调用reducer更新state