JavaScript 为什么能活到现在?
2019-11-08 17:23
1581 查看
原型方法的极大丰富;
类与模块的标准化;
异步机制的嬗变;
块级作用域的补完;
基础类型的增加;
反射机制的完善;
更顺手的语法糖。
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区块链代币平台的神秘面纱!
相关文章推荐
- 现在,为什么连一个 JavaScript 的厌恶者都认为:每个开发人员都应该学习 JavaScript
- 现在,为什么连一个 JavaScript 的厌恶者都认为:每个开发人员都应该学习 JavaScript(转)
- 为什么JavaScript现在和将来都是编程语言首选?
- 现在,为什么连一个 JavaScript 的厌恶者都认为:每个开发人员都应该学习 JavaScript
- BetterExplained 为什么你应该(从现在开始就)写博客
- 为什么你应该(从现在开始就)写博客
- <a href="onclick="javascript:goSearch(this)" class="click" name="Java">Java</a>为什么a标签的父节点获取不到
- 十万个为什么:现在还没发现“虚函数virtual”和多态性的优点,估计是因为我还没有编程序吧。
- 为什么现在的外贸建站这么的难呢
- javascript 为什么原型继承很重要
- 为什么要学javascript
- 关于如何在jsp通过javascript获取表单中的值,以及为什么登陆界面刷新以后图片都不见了得原因
- 轻松学习JavaScript一:为什么学习JavaScript
- javascript既然是单线程语言 , 为什么会分主线程和消息线程(event loop) ?
- [BetterExplained]为什么你应该(从现在开始就)写博客
- JavaScript 为什么不要使用 eval
- 深入学习JavaScript:在JavaScript中,为什么10..toString()正常,而10.toString()出错呢?(转)
- 为什么你应该(从现在开始就)写博客
- 为什么你应该(从现在开始就)写博客 转
- [BetterExplained]为什么你应该(从现在开始就)写博客 收藏