-
原型方法的极大丰富;
-
类与模块的标准化;
-
异步机制的嬗变;
-
块级作用域的补完;
-
基础类型的增加;
-
反射机制的完善;
-
更顺手的语法糖。
function Person(name) {
this.name = name;
}
//定义一个方法并且赋值给构造函数的原型
Person.prototype.sayName = function () {
return this.name;
};
var p = new Person('ruby');
console.log(p.sayName()) // ruby
class Person {
constructor(name){
this.name = name
}
sayName() {
return this.name;
}
}
var p = new Person('ruby');
console.log(p.sayName()) // ruby
//下面这种写法并不合法
class Person {
constructor: function(name){
this.name = name
}
sayName: function() {
return this.name;
}
}
class Person extends Animal {
constructor: function(name){
super();
this.name = name
}
sayName: function() {
return this.name;
}
}
<script>
标准还会导致页面渲染堵塞,出现白屏现象。<script src="zepto.js"></script>
<script src="jhash.js"></script>
<script src="fastClick.js"></script>
<script src="iScroll.js"></script>
<script src="underscore.js"></script>
<script src="handlebar.js"></script>
<script src="datacenter.js"></script>
<script src="util/wxbridge.js"></script>
<script src="util/login.js"></script>
<script src="util/base.js"></script>
define(['jquery'], function($){
//some code
var mod = require("./relative/name");
return {
//some code
} //返回值可以是对象、函数等
})
require(['cores/cores1', 'cores/cores2', 'utils/utils1', 'utils/utils2'], function(cores1, cores2, utils1, utils2){
//some code
})
define(function(require){
var $ = require("jquery");
$("#container").html("hello,seajs");
var service = require("./service")
var s = new service();
s.hello();
});
//另一个独立的文件service.js
define(function(require,exports,module){
function Service(){
console.log("this is service module");
}
Service.prototype.hello = function(){
console.log("this is hello service");
return this;
}
module.exports = Service;
});
-
https://github.com/seajs/seajs/issues/478
//world.js
exports.world = function() {
console.log('Hello World');
}
//main.js
let world = require('./world.js')
world();
function Hello() {
var name;
this.setName = function(thyName) {
name = thyName;
};
this.sayHello = function() {
console.log('Hello ' + name);
};
};
module.exports = Hello;
//test.js或test.mjs
import * as test from './test';
//aaa.js或aaa.mjs
import {aaa} from "./aaa"
const arr = [1, 2, 3, 4];
const obj = {
a: 0,
b: function() {}
}
export const foo = () => {
const a = 0;
const b = 20;
return a + b;
}
export default {
num,
arr,
obj,
foo
}
<link rel="modulepreload" href="lib.mjs">
<link rel="modulepreload" href="main.mjs">
<script type="module" src="main.mjs"></script>
<script nomodule src="fallback.js"></script>
A();
B();
C();
A();
// 在现在发送请求
ajax({
url: url,
data: {},
success:function(res){
// 在未来某个时刻执行
B(res)
}
})
C();
//执行顺序:A -> C -> B
// https://doc.quickapp.cn/features/system/share.html
import share from '@system.share'
share.share({
type: 'text/html',
data: '<b>bold</b>',
success: function(){},
fail: function(){},
complete: function(){}
})
fs.readFile('/foo.txt', function(err, data) {
// TODO: Error Handling Still Needed!
console.log(data);
});
var EventEmitter = require('events').EventEmitter;
var ee = new EventEmitter();
ee.on('some_events', function(foo, bar) {
console.log("第1个监听事件,参数foo=" + foo + ",bar="+bar );
});
console.log('第一轮');
ee.emit('some_events', 'Wilson', 'Zhong');
console.log('第二轮');
ee.emit('some_events', 'Wilson', 'Z');
var p = new Promise(function(resolve, reject){
console.log("========")
setTimeout(function(){
resolve(1)
},300)
setTimeout(function(){
//reject与resolve只能二选一
reject(1)
},400)
});
console.log("这个先执行")
p.then(function (result) {
console.log('成功:' + result);
})
.catch(function (reason) {
console.log('失败:' + reason);
}).finally(function(){
console.log("总会执行")
})
new Promise(executor)
里的executor方法,它会待到then, catch, finally等方法添加完,才会执行,它是异步的。而then, catch, finally则又恰好对应success, fail, complete这三种回调,我们可以为Promise以链式方式添加多个then方法。window.addEventListener('unhandledrejection', function(event) {
// the event object has two special properties:
alert(event.promise); // [object Promise] - 产生错误的 promise
alert(event.reason); // Error: Whoops! - 未处理的错误对象
});
new Promise(function() {
throw new Error("Whoops!");
}); // 没有 catch 处理错误
process.on('unhandledRejection', (reason, promise) => {
console.log('未处理的拒绝:', promise, '原因:', reason);
// 记录日志、抛出错误、或其他逻辑。
});
其实chrome 60已经都可以用了。
var promise1 = Promise.resolve(3);
var promise2 = 42;
var promise3 = new Promise(function(resolve, reject) {
setTimeout(resolve, 100, 'foo');
});
Promise.all([promise1, promise2, promise3]).then(function(values) {
console.log(values);
});
// expected output: Array [3, 42, "foo"]
let numbers = [1, 2, 3];
for (let i = 0; i < numbers.length; i++) {
console.log(numbers[i]);
}
//它比上面更精简
numbers.forEach(function(el){
console.log(el);
})
function makeIterator(array){
var nextIndex = 0;
return {
next: function(){
return nextIndex < array.length ?
{value: array[nextIndex++], done: false} :
{done: true};
}
};
}
var it = makeIterator([1,2,3])
console.log(it.next()); // {value: 1, done: false}
console.log(it.next()); // {value: 2, done: false}
console.log(it.next()); // {value: 3, done: false}
console.log(it.next()); // {done: true}
//理想中是这样的
Iterator{
exector(){
yield 1;
yield 2;
yield 3;
}
}
//现实是这样的
function* Iterator() {
yield 1;
yield 2;
yield 3;
}
function* Iterator() {
yield 1;
yield 2;
yield 3;
}
let it = Iterator();
console.log(it.next()); // {value: 1, done: false}
console.log(it.next()); // {value: 2, done: false}
console.log(it.next()); // {value: 3, done: false}
console.log(it.next()); // {value: undefined, done: true}
function* generator() {
yield 1;
return 2; //这个被转换成 yield 2, 并立即设置成done: true
yield 3; //这个被忽略
}
let it = generator();
console.log(it.next()); // {value: 1, done: false}
console.log(it.next()); // {value: 2, done: true}
console.log(it.next()); // {value: undefined, done: true}
function* generator() {
yield setTimeout(function(){ console.log("111"), 200})
yield setTimeout(function(){ console.log("222"), 100})
}
let it = generator();
console.log(it.next()); // 1 视浏览器有所差异
console.log(it.next()); // 2 视浏览器有所差异
function timeout(data, time){
return new Promise(function(resolve){
setTimeout(function(){
console.log(data, new Date - 0)
resolve(data)
},time)
})
}
function *generator(){
let p1 = yield timeout(1, 2000)
console.log(p1)
let p2 = yield timeout(2, 3000)
console.log(p2)
let p3 = yield timeout(3, 2000)
console.log(p3)
return 2;
}
// 按顺序输出 1 2 3
/* 传入要执行的gen */
/* 其实循环遍历所有的yeild (函数的递归)
根绝next返回值中的done判断是否执行到最后一个,
如果是最后一个则跳出去*/
function run(fn) {
var gen = fn();
function next(data) {
// 执行gen.next 初始data为undefined
var result = gen.next(data)
// 如果result.done 为true
if(result.done) {
return result.value
}else{
// result.value 为promise
result.value.then(val=>{
next(val)
})
}
}
// 调用上一个next方法
next();
}
run(generator)
//C# 代码
public static async Task<int> AddAsync(int n, int m) {
int val = await Task.Run(() => Add(n, m));
return val;
}
//javascript 代码
async function addTask() {
await new Promise(function(resolve){
setTimeout(function(){ console.log("111"); resolve(), 200})
})
console.log('222')
await new Promise(function(resolve){
setTimeout(function(){ console.log("333"); resolve(), 200})
})
console.log('444')
}
var p = addTask()
console.log(p)
const array = ["a","b", "c"]
function getNum(num){
return new Promise(function(resolve){
setTimeout(function(){
resolve(num)
}, 300)
})
}
async function asyncLoop() {
console.log("start")
for(let i = 0; i < array.length; i++){
const num = await getNum(array[i]);
console.log(num, new Date-0)
}
console.log("end")
}
asyncLoop()
async function addTask() {
try{
await ...
console.log('222')
}catch(e){
console.log(e)
}
}
//异步迭代器
const ruby = {
[Symbol.asyncIterator]: () => {
const items = [`r`, `u`, `b`, `y`, `l`, `o`,`u`, `v`, `r`, `e`];
return {
next: () => Promise.resolve({
done: items.length === 0,
value: items.shift()
})
}
}
}
for await (const item of ruby) {
console.log(item)
}
//异步生成器函数,async函数与生成器函数的混合体
async function* readLines(path) {
let file = await fileOpen(path);
try {
while (!file.EOF) {
yield await file.readLine();
}
} finally {
await file.close();
}
}
块级作用域的补完
try{
var name = 'global' //全局作用域
}catch(e){
var b = "xxx"
console.log(b)//xxx
}
console.log(b)
var obj = {
name: "block"
}
with(obj) {
console.log(name);//Block块上的name block
}
console.log(name)//global
var x = 1;
function rain(){
alert( x ); //弹出 'undefined',而不是1
var x = 'rain-man';
alert( x ); //弹出 'rain-man'
}
rain();
-
作用域是局部,作用范围是括起它的两个花括号间,即 for(){}
,while(){}
,if(){}
与单纯的{}
。 -
它也不会提升到作用域顶部,它顶部到定义的那一行变称之为“暂时性死区”,这时使用它会报错。 -
变量一旦变let, const声明,就再不能重复定义,否则也报错。这种严格的错误提示对我们调试是非常有帮助的。
let a = "hey I am outside";
if(true){
//此处存在暂时性死区
console.log(a);//Uncaught ReferenceError: a is not defined
let a = "hey I am inside";
}
//let与const不存在变量提升
console.log(a); // Uncaught ReferenceError: a is not defined
console.log(b); // Uncaught ReferenceError: b is not defined
let a = 1; //Uncaught SyntaxError: Identifier 'a' has already been declared
const b = 2;
//不存在变量提升,因此块级作用域外层无法访问
if(true){
var bar = "bar";
let baz = "baz";
const qux = "qux";
}
console.log(bar);//bar
console.log(baz);//baz is not defined
console.log(qux);//qux is not defined
console.log(typeof 9007199254740991n); // "bigint"
console.log(typeof Symbol("aaa")); // "symbol"
const COLOR_GREEN = 1
const COLOR_RED = 2
const LALALA = 1;
function isSafe(args) {
if (args === COLOR_RED) return false
if (args === COLOR_GREEN) return true
throw new Error(`非法的传参: ${args}`)
}
console.log(isSafe(COLOR_GREEN)) //true
console.log(isSafe(COLOR_RED)) //false
console.log(isSafe(LALALA)) //true
const COLOR_GREEN = Symbol("1")//传参可以是字符串,数字,布尔或不填
const COLOR_RED = Symbol("2")
const LALALA = Symbol("1")
function isSafe(args) {
if (args === COLOR_RED) return false
if (args === COLOR_GREEN) return true
throw new Error(`非法的传参: ${args}`)
}
console.log(isSafe(COLOR_GREEN)) //true
console.log(isSafe(COLOR_RED)) //false
console.log(COLOR_GREEN == LALALA) //false
console.log(isSafe(LALALA)) //throw error
注意,Symbol不是一个构造器,不能new。 new Symbel("222")
会抛错。
for in
遍历出来。而Symbol属性不一样,遍历不出来,因此适用做对象的私有属性,因为你只有知道它的名字,才能访问到它。var a = {
b: 11,
c: 22
}
var d = Symbol();
a[d] = 33
for(var i in a){
console.log(i, a[i]) //只有b,c
}
ar d = Symbol("11")
console.log(d - 1)
Symbol.for("foo"); // 创建一个 symbol 并放入 symbol 注册表中,键为 "foo"
Symbol.for("foo"); // 从 symbol 注册表中读取键为"foo"的 symbol
Symbol.for("bar") === Symbol.for("bar"); // true,证明了上面说的
Symbol("bar") === Symbol("bar"); // false,Symbol() 函数每次都会返回新的一个 symbol
var sym = Symbol.for("mario");
sym.toString();
let s1 = Symbol.for("111");
console.log( Symbol.keyFor(s1) ) // "111"
console.log(s1.description) // "111"
let s2 = Symbol("222");
console.log( Symbol.keyFor(s2)) // undefined
console.log(s2.description) // "222"
let s3 = Symbol.for(111);
console.log( Symbol.keyFor(s3) ) // "111"
console.log(s3.description) // "111"
iframe = document.createElement('iframe');
iframe.src = String(window.location);
document.body.appendChild(iframe);
iframe.contentWindow.Symbol.for('111') === Symbol.for('111')// true
for of
循环,相对于for in
循环,它是直接遍历出值。究其原因,是因为数组原型上添加Symbol.iterator,它就是一个内置的迭代器,而for of
就是执行函数的语法。像数组,字符串,arguments, NodeList, TypeArray, Set, Map, WeakSet, WeatMap的原型都加上Symbol.iterator,因此都可以用for of
循环。console.log(Symbol.iterator in new String('sss')) // 将简单类型包装成对象才能使用in
console.log(Symbol.iterator in [1,2,3] )
console.log(Symbol.iterator in new Set(['a','b','c','a']))
for(var i of "123"){
console.log(i) //1,2 3
}
for of
循环则遇到异常,需要我们自行添加。Object.prototype[Symbol.iterator] = function() {
var keys = Object.keys(this);
var index = 0;
return {
next: () => {
var obj = {
value: this[keys[index]],
done: index+1 > keys.length
};
index++;
return obj;
}
};
};
var a = {
name:'ruby',
age:13,
home:"广东"
}
for (var val of a) {
console.log(val);
}
for await of
循环一起使用,见上面异步一节。class Search1 {
constructor(value) {
this.value = value;
}
[Symbol.search](string) {
return string.indexOf(this.value);
}
}
console.log('foobar'.search(new Search1('bar')));
class Replace1 {
constructor(value) {
this.value = value;
}
[Symbol.replace](string) {
return `s/${string}/${this.value}/g`;
}
}
console.log('foo'.replace(new Replace1('bar')));
class Split1 {
constructor(value) {
this.value = value;
}
[Symbol.split](string) {
var index = string.indexOf(this.value);
return this.value + string.substr(0, index) + "/"
+ string.substr(index + this.value.length);
}
}
console.log('foobar'.split(new Split1('foo')));
class ValidatorClass {
get [Symbol.toStringTag]() {
return 'Validator';
}
}
console.log(Object.prototype.toString.call(new ValidatorClass()));
// expected output: "[object Validator]"
console.log(1234567890123456789 * 123) //这显然不对
const theBiggestInt = 9007199254740991n;
const alsoHuge = BigInt(9007199254740991);
// ↪ 9007199254740991n
const hugeString = BigInt("9007199254740991");
// ↪ 9007199254740991n
const hugeHex = BigInt("0x1fffffffffffff");
// ↪ 9007199254740991n
const hugeBin = BigInt("0b11111111111111111111111111111111111111111111111111111");
console.log(typeof hugeBin) //bigint
反射机制的完善
var inner = 0;
var obj = {
set a(val){
console.log("set a ")
inner = val
},
get a(){
console.log("get a ")
return inner +2
}
}
console.log(obj)
obj.a = 111
console.log(obj.a) // 113
var inner = 0;
var obj = {}
Object.defineProperty(obj, 'a', {
set:function(val){
console.log("set a ")
inner = val
},
get: function(){
console.log("get a ")
return inner +2
}
})
console.log(obj)
obj.a = 111
console.log(obj.a) // 113
__defineGetter__
, __defineSetter__
,它们是挂在对象的原型链上。var inner = 0;
var obj = {}
obj.__defineSetter__("a", function(val){
console.log("set a ")
inner = val
})
obj.__defineGetter__("a", function(){
console.log("get a ")
return inner + 4
})
console.log(obj)
obj.a = 111
console.log(obj.a) // 115
let p = new Proxy({}, {//拦截对象,上面有如下拦截器
get: function(target, name){
// obj.aaa
},
set: function(target, name, value){
// obj.aaa = bbb
},
construct: function(target, args) {
//new
},
apply: function(target, thisArg, args) {
//执行某个方法
},
defineProperty: function (target, name, descriptor) {
// Object.defineProperty()
},
deleteProperty: function (target, name) {
//delete
},
has: function (target, name) {
// in
},
ownKeys: function (target, name) {
// Object.getOwnPropertyNames()
// Object.getOwnPropertySymbols()
// Object.keys() Reflect.ownKeys()
},
isExtensible: function(target) {
// Object.isExtensible()。
},
preventExtensions: function(target) {
// Object.preventExtensions()
},
getOwnPropertyDescriptor: function(target, prop) {
// Object.getOwnPropertyDescriptor()
},
getPrototypeOf: function(target){
// Object.getPrototypeOf(),
// Reflect.getPrototypeOf(),
// __proto__
// Object.prototype.isPrototypeOf()与instanceof
},
setPrototypeOf: function(target, prototype) {
// Object.setPrototypeOf().
}
});
var p = new Proxy({
a: 11
}, {
deleteProperty: function (target, name) {
console.log(arguments)
return Reflect.deleteProperty(target, name)
}
})
delete p.a
Reflect.apply(target, thisArg, args)
Reflect.construct(target, args)
Reflect.get(target, name, receiver)
Reflect.set(target, name, value, receiver)
Reflect.defineProperty(target, name, desc)
Reflect.deleteProperty(target, name)
Reflect.has(target, name)
Reflect.ownKeys(target)
Reflect.isExtensible(target)
Reflect.preventExtensions(target)
Reflect.getOwnPropertyDescriptor(target, name)
Reflect.getPrototypeOf(target)
Reflect.setPrototypeOf(target, prototype)
-
对象简写,参看类的组织形式
-
扩展运算符(
…
),用于对象的浅拷贝 -
箭头函数,省略function关键字,与数学公式走近,能绑定this与略去return
-
for of(遍历可迭代对象的所有值, for in是遍历对象的键或索引)
-
数字格式化, 如1_222_333
-
字符串模板化与天然多行支持,如
hello ${world}
-
幂运算符,
**
-
可选链,
let x = foo?.bar.baz();
-
空值合并运算符,
let x = foo ?? bar();
-
函数的默认参数
【END】
热 文 推 荐
☞这款“狗屁不通”文章生成器火了,效果确实比GPT 2差太远
☞CSDN应邀赴微软IT大会,揭开微软重磅推出的秘密武器——Azure区块链代币平台的神秘面纱!
文章评论