JS科普帖

前言

不同语言有不同的范式、思想
了解不同的范式,有助于思路、思维的启发。所谓触类旁通
computer语言始终是工具、武器,而不是拿来争论的谈资,可以为我所用,而不必为之所限

口号: 学习js 为自己赋能

简介

一门非常灵活的 动态 、弱类型 语言

反直觉:
1 性能 2 难度

语言热榜(只是排行和好坏无关)


image.png

跑个分:


image.png

参考(仅参考不必较真):
https://benchmarksgame-team.pages.debian.net/benchmarksgame/index.html
https://goodmanwen.github.io/Programming-Language-Benchmarks-Visualization/

历史

90年代, Brendan Eich 给 Netscape 开发的浏览器辅助语言 Mocha(后更名为 JavaScript),耗时10天出原型(包含了eval 函数),集成到 Netscape 2预览版里,Mocha 基于对象而非 Java 那样基于类。

Mocha 的动态的对象模型,使用原型链的机制。

Netscape 2 正式版将 Mocha 更名为 JavaScript,后简称 js。

1.0 版本 js 语法大量借鉴 C 语言。行末可不加分号,一开始 js 就是支持的。

1.1版 js 支持隐式类型转换,可以把任意对象转成数字和字符串。1.0版 js 对象不能继承,1.1 加入对象的 prototype 属性,prototype 的属性和实例的对象共享。
为了加到 ISO 标准中,Netscape 找到了 Ecma,因为 ISO 对 Ecma 这个组织是认可的。接着 Ecma 组建了 TC39 技术委员会负责创建和维护 js 的规范。

期间,微软为了能够兼容 js,组建了团队开发 JScript,微软自己摸索然后开发,并写了份规范 The JScript Language Specification, version 0.1 提交给 TC39,微软还将 VBScript 引入 IE。96年 Netscape 为 JavaScript 1.1 写了规范 Javascript 1.1 Specification in Winword format 作为 TC39 标准化 js 的基础。

97年 TC39 发布了 ECMA-262 第一版规范。

Netscape 3 发布后,Brendan Eich 重构了 js 引擎核心,加了嵌套函数、lambda、正则表达式、伪属性(动态访问修改对象)、对象和数组的字面量、基于标记和清除的 GC。lambda 的函数名为可选,运行时会创建闭包,闭包可递归引用自己作为参数。新 js 引擎叫 SpiderMonkey。增加break / continue 标签语句以及 switch。语言升级为 JavaScript 1.2,和 SpiderMonkey 一起集成到 Netscape 4.0。

ES3 结合了 js 1.2 和 JScript 3.0,标准坚持了10年。

2006年 Google 的 Lars Bak 开始了 V8 引擎的开发,2008 基于 V8 的 Chrome 浏览器发布,性能比 SpiderMonkey 快了10倍。

Ryan Dahl 2009 开发了 Node.js ,提供标准库让 js 能够建立 HTTP 服务端应用。此后js就不再局限于前端领域了
ES4 初期目标是希望能够支持类、模块、库、package、Decimal、线程安全等。

这一版本ES4太激进, 很多特性无法通过,而没法通过标准,因此同步设计了10年多的 ES 3.1 最终改名为 ES5
2015年,(ECMAScript 2015)[]发布。这是改动最多的一个版本,加入了大量的语法特性,此后每年发布一版标准

ES6特性

箭头函数、Promise、迭代器....

应用场景

前端、服务端、脚本工具

基础语法

变量声明

const
let
var

类型

number、string、symbol、undefined、null、object、array、function

常见编码规范

switch、for、 if、new
语法参考了C 家族的风格:
条件判断、for循环都需要放到()里
switch需要手动break

for (let i =0 ; i<3; i++){
    // do something
}

switch ("some var") {
case "some var":
    // logic
    break
case "other":
    // ...
}

class A{}
const a = new A();  // 符合直觉的创建对象

解构

let obj = {hello:"world"};
let {hello} = obj;
console.log(hello);

let obj2 = {obj};
console.log(obj2);

遍历

for

let arr = [1,2,3];

for (let i = 0; i < arr.length; i++){
    console.log(arr[i])
}

for (let i in arr){
    console.log(arr[i]);
}

for (let i of arr){  // es6 新增  实现迭代器接口即可 使用此种遍历方式
    console.log(i);  // 注意此处直接取到value
}

arr.forEach(i=> console.log(i));  // 闭包形式 不支持break、continue

let arrMulti = arr.map(i=>i*i);  // 返回值

let obj = {a:"a", b:3};

for (let i in obj){
    console.log(i, "value", obj[i]);
}

for (let i of Object.keys(obj)){   // 对象未实现 iterator接口
    console.log(i, "value", obj[i]);
}

while、do...while

函数

1 复用代码

2 构造对象

function makeObj(){
    this.name = "new obj";
}

let o = new makeObj();
console.log(o)

3 箭头函数

const arrow = (params1, params2) =>{
    console.log('abc');
};
// 简写
arrow = (params1, params2) =>console.log('abc');

// 单参数可忽略括号
arrow = params =>console.log('abc');

一般高阶函数的参数(闭包)可用箭头函数

const pro = new Pormise(function(resolve, reject){ resolve('async resolve')});

其次,也可以当做普通函数使用,且不可以当做构造函数

const print = ()=> console.log('hello world');
const obj = new print(); // error

箭头函数没有自己的this

闭包

特征:

1 闭包是(一种特殊的)function
2 闭包一般作为高阶函数的参数或嵌套定义的function
3 闭包[调用态]捕获(感知)所在作用域、作用域外层上下文

js世界中的闭包应用非常广泛
1 js最初是浏览器环境运行的,运行时单线程,早先异步都是通过回调函数来实现,回调函数即最常见的闭包运用场景

request("baidu.com", function(err, response){
    if (err){
     throw "bad request";
    }
    console.log(response.status)
})

2 给DOM元素注册监听函数

// 这里是 ctx  let someVar = ...
document.addEventListener("foo", event => { // 在 document 上绑定 foo 事件的监听函数
      event.preventDefault()
      // do something ...
    }
}

应用:

// 模拟私有变量
function makeIncrement(){
    let __somePrivate = 1;  // 此变量外界无法干预
    return function(){
        // 有内存泄漏嫌疑
        return __somePrivate++;   // 注意前后缀++运算符区别
    }
}

let incementer = makeIncrement();
let count = incrementer(); // 1
count = incrementer(); // 2

语法迷思

js有很多操作其实都是反直觉的

原型链

如果用传统面向对象语言类比,那么原型链是类与类之间的关系,此处需要区别类 和实例

领域关键字

arguments
this:
传统面向对象语言中的this

class MyObj{
    constructor(name: string){  // 构造器
        this.name = name;
    }
    say(){
        console.log(`my name is ${this.name}`);
    }
}

let obj = new MyObj("xiao zhang");
obj.say();

bind、call、apply
slice、substr、substring

this解谜

1 this绑定

四种绑定方式
遵循以下优先级
new绑定 > 显式绑定 > 隐式绑定 > 默认绑定

new
function A(){
    this.a = "a";
}
let a = new A();
显式
function Greeting(){
    this.name = 'zhansan';
    this.greeting = function(){
       console.log(`hello ${this.name}`)
    }
}
const obj = {name : "wangwu"};
new Greeting().greeting.call(obj);
隐式
const obj = {
    name: 'zhangsan',
    greeting: function(){
       console.log(`hello ${this.name}`)
    }
}
obj.greeting();
const obj2 = {name:"aaa"};
obj2.hello = obj.greeting;
obj2.hello();
默认

其他方式都算做默认绑定

2 箭头函数this

1 不准确的说法
箭头函数指向外层
箭头函数this始终不变

let obj = {
    a: ()=> console.log(this),
};
obj.a();
obj = function(){
    this.a = ()=> console.log(this);
}
new obj().a();

obj = {
    a:  {
        b: ()=> console.log(this),
    },
};
obj.a.b();

obj = {
    a:  function(){
        return ()=> console.log(this);
    },
};
obj.a()();
// 箭头函数this始终指向外层【函数】所绑定的作用域
// 箭头函数this始终不变 是错误的说法
let b = {b:"b"};
b.a = obj.a;
b.a()();

obj = {
    a:  function(){
        this.hello = 'world';
        this.b = ()=> console.log(this);
    },
};
new obj.a().b();

3 规则

this的值在函数被调用的时候才会指定

应用解答

前置知识

var关键字

1 挂载到window对象
2 变量不经申明也挂载到window对象下
坑点: 全局变量污染

function b(){
    c = 18;
}
b();
console.log(c);

3 没有块级别作用域

if (true){
    var hello = 'world';
}
console.log(hello);
var和let区别

1 不挂载window
2 有块级别作用域

var number = 5;
var obj = {
    number: 3,
    fn1: (function () {
        var number;   // undefined
        this.number *= 2;  // 10
        number = number * 2;  // NaN
        number = 3;   // bibao.number = 3
        return function () {
            //  this == obj
            var num = this.number;  // num = 10  、3
            this.number *= 2;  // this.number = 20  、6
            console.log(num);  // print 10   3
            number *= 3;   // bibao.number = 9   、27
            console.log(number);  //print 9   27
        }
    })()
}
var fn1 = obj.fn1;
fn1.call(null);  // window.fn1()
obj.fn1();
console.log(window.number);  // 20

Promise API

| 天不生ES6 JS万古如长夜
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。

构造函数

// 主意构造方法  比较独特
const myPromise = new Promise((resolve, reject)=>{
    if (// 异步操作成功)  resolve('success');
    reject('error');
})

// then  方法接收两个函数 分别是成功和失败的处理
myPromise.then(()=> console.log('hello world'))

此时 myPromise 是一个thenable 对象, 且通过then方法返回的也是 promise对象

特点

对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。
一旦状态改变,就不会再变,任何时候都可以得到这个结果。

实例方法

所有promise 对象的实例方法均会返回promise对象,从而可以形成调用链

const obj = new Promise(function(reslove, reject){
    // do somthing
    resolve();
})
obj.then(()=> consolt.log('hello world')).
catch(e=> console.log(e)).finally(()=>console.log('over'));

// then 方法接收两个参数
obj.then((rst)=>console.log('success with result ', rst),
err => console.log(err)
)
// catch 是 then(null, rejection)的快捷方式  一般推荐catch方式处理失败情况
obj.then((rst)=>console.log('success with result ', rst)).
catch(err => console.log(err));

// catch 可以处理  构造函数里  reject 抛出的错误 
// 也可以处理 resolve或 then 里通用代码抛出的异常
obj.then(()=>{
    throw new Error('err')
}).catch((e)=>console.log(`catch error ${e}`));

// 此时如果没有catch 的话则会抛出运行时异常

静态方法

Promsie.all

 const p = Promise.all([p1, p2, p3]);

Promise.all()方法接受一个数组作为参数,p1、p2、p3都是 Promise 实例,如果不是,就会先调用下面讲到的Promise.resolve方法,将参数转为 Promise 实例,再进一步处理。另外,Promise.all()方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例。

p的状态由p1、p2、p3决定,分成两种情况。(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

Promise.race

Promise.allSettled

Promise.resolve

Promise.resolve('foo')
// 等价于
new Promise(resolve => resolve('foo'))
// resolve方法相当于一个快捷方式  

resolve的参数:
1 promise对象则原封不动返回
2 thenable 对象则立即执行then方法然后返回结果对象的promise包装
3 其他则包装参数中内容为 resolve状态的promise对象

何谓thenable
let thenable = {
  then: function(resolve, reject) {
    resolve(42);
  }
};

Promise.reject

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容

  • 背景 1995 年 Netscape 公司的 Brendan Eich 创造了 Javascript。 1996 ...
    紫山坡下阅读 243评论 0 0
  • 入门与进阶 第一章 进入编程 1,如何快速运行一段js代码? 方式1:浏览器开发者工具。可以使用快捷键option...
    潇潇潇潇潇潇潇阅读 851评论 0 0
  • 1. JS创建变量的5种方式?varletconstfunctionexport/import 2. var,le...
    Angel_6c4e阅读 811评论 0 13
  • 1.事件冒泡与事件捕获 事件冒泡:由最具体的元素(目标元素)向外传播到最不具体的元素事件捕获:由最不确定的元素到目...
    吃肉肉不吃肉肉阅读 191评论 0 1
  • 1.自执行函数?用于什么场景?好处? 自执行函数:1、声明一个匿名函数2、马上调用这个匿名函数。作用:创建一个独立...
    一只小丫丫阅读 171评论 0 0