参考(https://segmentfault.com/a/1190000003818502)
毕业到现在都没正经学过js,最近在看vue发现我的js就是土著啊。什么时候冒出这种写发
箭头函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26// 使用表达式(Expression bodies)
var odds = evens.map(v => v + 1);
var nums = evens.map((v, i) => v + i);
// 使用函数体(Statement bodies)
nums.forEach(v => {
if (v % 5 === 0)
fives.push(v);
});
// this 对象
var bob = {
_name: "Bob",
_friends: [],
printFriends() {
this._friends.forEach(f =>
console.log(this._name + " knows " + f)
);
},
// _printFriend 为译者添加 是使用function时的等价写法
_printFriends() {
this._friends.forEach(function(f){
console.log(this._name + " knows " + f)
}.bind(this))
}
};类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19class SkinnedMesh extends THREE.Mesh {
constructor(geometry, materials) {
// 调用父类的构造函数 super是父类的实例
super(geometry, materials);
this.idMatrix = SkinnedMesh.defaultMatrix();
this.bones = [];
this.boneMatrices = [];
//...
}
update(camera) {
//...
super.update();
}
// 静态方法
static defaultMatrix() {
return new THREE.Matrix4();
}
}==增强的对象字面量==(这里我先打个问号,不知道他增强了什么。因为我之前也不知道他干了什么,有待后期!!)
模板字符串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20// 创建基本的模板字符串
`This is a pretty little template string.`
// 多行字符串
`In ES5 this is
not legal.`
// 插入变量
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`
// 在模板字符串中不使用转义
String.raw`In ES5 "\n" is a line-feed.`
// 创建一个HTTP请求头的模板字符串,通过替换内容来构建请求
GET`http://foo.org/bar?a=${a}&b=${b}
Content-Type: application/json
X-Credentials: ${credentials}
{ "foo": ${foo},
"bar": ${bar}}`(myOnReadyStateChangeHandler);解构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24// 列表(数组)匹配
var [a, , b] = [1,2,3];
// 对象匹配
var { op: a, lhs: { op: b }, rhs: c }
= getASTNode()
// 对象匹配的简写
// 绑定当前作用域的 `op`, `lhs` 和 `rhs`
var {op, lhs, rhs} = getASTNode()
// 可以用在函数的参数中
function g({name: x}) {
console.log(x);
}
g({name: 5})
// 弱化解构
var [a] = [];
a === undefined;
// Fail-soft destructuring with defaults
var [a = 1] = [];
a === 1;默认参数(Default) + 不定参数(Rest) + 扩展运算符(Spread)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20//默认参数
function f(x, y=12) {
// y is 12 if not passed (or passed as undefined)
return x + y;
}
f(3) == 15
//不定参数
function f(x, ...y) {
// ...运算符将x之后的参数转换为名为y的数组
return x * y.length;
}
f(3, "hello", true) == 6
//扩展运算符
function f(x, y, z) {
return x + y + z;
}
// ...运算符将数组转换为连续的参数
f(...[1,2,3]) == 6Let(局部变量) + Const(常量)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15function f() {
{
let x;
{
// 可以执行,因为是在块级作用域内
const x = "sneaky";
// 错误,常量不允许被赋值
x = "foo";
}
// 可以执行,因为是使用let声明
x = "bar";
// 错误,在当前块级作用域内已经被声明了一次
let x = "inner";
}
}迭代器(Iterators) + For..Of循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19// 实现斐波那契数列的迭代器
let fibonacci = {
[Symbol.iterator]() {
let pre = 0, cur = 1;
return {
next() {
[pre, cur] = [cur, pre + cur];
return { done: false, value: cur }
}
}
}
}
for (var n of fibonacci) {
// 循环将在n > 1000 时结束
if (n > 1000)
break;
console.log(n);
}
参考https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Iteration_protocols
可迭代协议:为了变成可迭代对象, 一个对象必须实现 @@iterator 方法, 意思是这个对象(或者它原型链prototype chain上的某个对象)必须有一个名字是 Symbol.iterator 的属性(返回一个对象的无参函数,被返回对象符合==迭代器协议==)
当一个对象需要被迭代的时候(比如开始用于一个for..of循环中),它的@@iterator方法被调用并且无参数,然后返回一个用于在迭代中获得值的迭代器。
迭代器协议:它实现了一个 next() 的方法并且返回{ done: false, value: cur }
done (boolean)
如果迭代器已经经过了被迭代序列时为 true。这时 value 可能描述了该迭代器的返回值。返回值在这里有更多解释。
如果迭代器可以产生序列中的下一个值,则为 false。这等效于连同 done 属性也不指定。
value - 迭代器返回的任何 JavaScript 值。done 为 true 时可省略
Generator(和py的生成器类似)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19// 实现斐波那契数列
var fibonacci = {
[Symbol.iterator]: function*() {
var pre = 0, cur = 1;
for (;;) {
var temp = pre;
pre = cur;
cur += temp;
yield cur;
}
}
}
for (var n of fibonacci) {
// truncate the sequence at 1000
if (n > 1000)
break;
console.log(n);
}模块
1
2
3
4
5// lib/math.js
export function sum(x, y) {
return x + y;
}
export var pi = 3.141593;
1 | // app.js |
1 | // otherApp.js |
以及一些额外的功能:export default和export *1
2
3
4
5
6// lib/mathplusplus.js
export * from "lib/math";
export var e = 2.71828182846;
export default function(x) {
return Math.exp(x);
}
1 | // app.js |
模块加载器(Module Loaders)
1
2
3
4
5
6
7
8
9
10
11
12
13
14// 动态加载 – ‘System’ 是默认的加载器
System.import("lib/math").then(function(m) {
alert("2π = " + m.sum(m.pi, m.pi));
});
// 创建执行沙箱 – new Loaders
var loader = new Loader({
global: fixup(window) // replace ‘console.log’
});
loader.eval("console.log(\"hello world!\");");
// 直接操作模块的缓存
System.get("jquery");
System.set("jquery", Module({$: $})); // WARNING: not yet finalizedMap + Set + WeakMap + WeakSet
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22// Sets
var s = new Set();
s.add("hello").add("goodbye").add("hello");
s.size === 2; //true
s.has("hello") === true; //true
// Maps
var m = new Map();
m.set("hello", 42);
m.set(s, 34);
m.get(s) == 34; //true
// Weak Maps
var wm = new WeakMap();
wm.set(s, { extra: 42 });
wm.size === undefined
// Weak Sets
var ws = new WeakSet();
ws.add({ data: 42 });
// 由于传入的对象没有其他引用,故将不会被set保存。
//这些作为属性键的对象如果没有别的变量在引用它们,则会被回收释放掉。Proxies(代理对象)
参考https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy1
2
3
4
5
6
7
8
9
10// 代理普通对象
var target = {};
var handler = {
get: function (receiver, name) {
return `Hello, ${name}!`;
}
};
var p = new Proxy(target, handler);
p.world === "Hello, world!"; //true
target:用Proxy包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
handler:一个对象,其属性是当执行一个操作时定义代理的行为的函数。
Symbols
Symbol对对象的状态进行访问控制。Symbol允许对象的属性不仅可以通过string(ES5)命名,还可以通过symbol命名。symbol是一种基本数据类型。可选的name参数用于调试——但并不是他本身的一部分。Symbol是唯一的,但不是私有的,因为他们使用诸如Object.getOwnPropertySymbols这样的方法来使用。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21(function() {
// 模块内的symbol
var key = Symbol("key");
function MyClass(privateData) {
this[key] = privateData;
}
MyClass.prototype = {
doStuff: function() {
... this[key] ...
}
};
// 被Babel部分支持,原生环境可以完全实现。
typeof key === "symbol"
})();
var c = new MyClass("hello")
c["key"] === undefined可以创建内建对象的子类
1
2
3
4
5
6
7
8// 创建Array的子类
class MyArray extends Array {
constructor(...args) { super(...args); }
}
var arr = new MyArray();
arr[1] = 12;
arr.length == 2Math + Number + String + Object APIs
新增很多功能,如核心的Math库,数组转换和用于对象复制的Object.assign()。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20Number.EPSILON
Number.isInteger(Infinity) // false
Number.isNaN("NaN") // false
Math.acosh(3) // 1.762747174039086
Math.hypot(3, 4) // 5
Math.imul(Math.pow(2, 32) - 1, Math.pow(2, 32) - 2) // 2
"abcde".includes("cd") // true
"abc".repeat(3) // "abcabcabc"
Array.from(document.querySelectorAll("*")) // 将类似数组的对象转换为真正的数组
Array.of(1, 2, 3) // 类似与new Array(),但是当仅有一个参数时,两者表现不同
[0, 0, 0].fill(7, 1) // [0,7,7]
[1,2,3].findIndex(x => x == 2) // 1
["a", "b", "c"].entries() // 迭代结果 [0, "a"], [1,"b"], [2,"c"]
["a", "b", "c"].keys() // 迭代结果 0, 1, 2
["a", "b", "c"].values() // 迭代结果 "a", "b", "c"
Object.assign(Point, { origin: new Point(0,0) })
二进制和八进制字面量
1
20b111110111 === 503 // true
0o767 === 503 // truePromises
Promises是一种异步编程的方式。Promises在将来可能会得到支持。目前很多的JavaScript库都使用了Promises。
参考https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise
http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html1
2
3
4
5
6
7
8
9
10
11
12
13function timeout(duration = 0) {
return new Promise((resolve, reject) => {
setTimeout(resolve, duration);
})
}
var p = timeout(1000).then(() => {
return timeout(2000);
}).then(() => {
throw new Error("hmm");
}).catch(err => {
return Promise.all([timeout(100), timeout(200)]);
})
- Reflect API
1
2
3
4
5
6
7
8
9
10
11var O = {a: 1};
Object.defineProperty(O, 'b', {value: 2});
O[Symbol('c')] = 3;
Reflect.ownKeys(O); // ['a', 'b', Symbol(c)]
function C(a, b){
this.c = a + b;
}
var instance = Reflect.construct(C, [20, 22]);
instance.c; // 42
总结:以上只是初步了解,相信在之后的js路上会经常遇到