JS科普帖

前言

不同語言有不同的范式绅你、思想
了解不同的范式伺帘,有助于思路、思維的啟發(fā)忌锯。所謂觸類旁通
computer語言始終是工具伪嫁、武器,而不是拿來爭論的談資偶垮,可以為我所用张咳,而不必為之所限

口號: 學(xué)習(xí)js 為自己賦能

簡介

一門非常靈活的 動態(tài) 帝洪、弱類型 語言

反直覺:
1 性能 2 難度

語言熱榜(只是排行和好壞無關(guān))


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 開發(fā)的瀏覽器輔助語言 Mocha(后更名為 JavaScript)脚猾,耗時10天出原型(包含了eval 函數(shù))葱峡,集成到 Netscape 2預(yù)覽版里,Mocha 基于對象而非 Java 那樣基于類龙助。

Mocha 的動態(tài)的對象模型砰奕,使用原型鏈的機制。

Netscape 2 正式版將 Mocha 更名為 JavaScript提鸟,后簡稱 js军援。

1.0 版本 js 語法大量借鑒 C 語言。行末可不加分號称勋,一開始 js 就是支持的胸哥。

1.1版 js 支持隱式類型轉(zhuǎn)換,可以把任意對象轉(zhuǎn)成數(shù)字和字符串赡鲜。1.0版 js 對象不能繼承烘嘱,1.1 加入對象的 prototype 屬性,prototype 的屬性和實例的對象共享蝗蛙。
為了加到 ISO 標準中,Netscape 找到了 Ecma醉鳖,因為 ISO 對 Ecma 這個組織是認可的捡硅。接著 Ecma 組建了 TC39 技術(shù)委員會負責創(chuàng)建和維護 js 的規(guī)范。

期間盗棵,微軟為了能夠兼容 js壮韭,組建了團隊開發(fā) JScript,微軟自己摸索然后開發(fā)纹因,并寫了份規(guī)范 The JScript Language Specification, version 0.1 提交給 TC39喷屋,微軟還將 VBScript 引入 IE。96年 Netscape 為 JavaScript 1.1 寫了規(guī)范 Javascript 1.1 Specification in Winword format 作為 TC39 標準化 js 的基礎(chǔ)瞭恰。

97年 TC39 發(fā)布了 ECMA-262 第一版規(guī)范屯曹。

Netscape 3 發(fā)布后,Brendan Eich 重構(gòu)了 js 引擎核心惊畏,加了嵌套函數(shù)恶耽、lambda、正則表達式颜启、偽屬性(動態(tài)訪問修改對象)偷俭、對象和數(shù)組的字面量、基于標記和清除的 GC缰盏。lambda 的函數(shù)名為可選涌萤,運行時會創(chuàng)建閉包淹遵,閉包可遞歸引用自己作為參數(shù)。新 js 引擎叫 SpiderMonkey负溪。增加break / continue 標簽語句以及 switch透揣。語言升級為 JavaScript 1.2,和 SpiderMonkey 一起集成到 Netscape 4.0笙以。

ES3 結(jié)合了 js 1.2 和 JScript 3.0淌实,標準堅持了10年。

2006年 Google 的 Lars Bak 開始了 V8 引擎的開發(fā)猖腕,2008 基于 V8 的 Chrome 瀏覽器發(fā)布拆祈,性能比 SpiderMonkey 快了10倍。

Ryan Dahl 2009 開發(fā)了 Node.js 倘感,提供標準庫讓 js 能夠建立 HTTP 服務(wù)端應(yīng)用放坏。此后js就不再局限于前端領(lǐng)域了
ES4 初期目標是希望能夠支持類、模塊老玛、庫淤年、package、Decimal蜡豹、線程安全等麸粮。

這一版本ES4太激進, 很多特性無法通過镜廉,而沒法通過標準弄诲,因此同步設(shè)計了10年多的 ES 3.1 最終改名為 ES5
2015年,(ECMAScript 2015)[]發(fā)布娇唯。這是改動最多的一個版本齐遵,加入了大量的語法特性,此后每年發(fā)布一版標準

ES6特性

箭頭函數(shù)塔插、Promise梗摇、迭代器....

應(yīng)用場景

前端、服務(wù)端想许、腳本工具

基礎(chǔ)語法

變量聲明

const
let
var

類型

number伶授、string、symbol伸刃、undefined谎砾、null、object捧颅、array景图、function

常見編碼規(guī)范

switch、for碉哑、 if挚币、new
語法參考了C 家族的風格:
條件判斷亮蒋、for循環(huán)都需要放到()里
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();  // 符合直覺的創(chuàng)建對象

解構(gòu)

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 新增  實現(xiàn)迭代器接口即可 使用此種遍歷方式
    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)){   // 對象未實現(xiàn) iterator接口
    console.log(i, "value", obj[i]);
}

while妆毕、do...while

函數(shù)

1 復(fù)用代碼

2 構(gòu)造對象

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

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

3 箭頭函數(shù)

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

// 單參數(shù)可忽略括號
arrow = params =>console.log('abc');

一般高階函數(shù)的參數(shù)(閉包)可用箭頭函數(shù)

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

其次慎玖,也可以當做普通函數(shù)使用,且不可以當做構(gòu)造函數(shù)

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

箭頭函數(shù)沒有自己的this

閉包

特征:

1 閉包是(一種特殊的)function
2 閉包一般作為高階函數(shù)的參數(shù)或嵌套定義的function
3 閉包[調(diào)用態(tài)]捕獲(感知)所在作用域笛粘、作用域外層上下文

js世界中的閉包應(yīng)用非常廣泛
1 js最初是瀏覽器環(huán)境運行的趁怔,運行時單線程,早先異步都是通過回調(diào)函數(shù)來實現(xiàn)薪前,回調(diào)函數(shù)即最常見的閉包運用場景

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

2 給DOM元素注冊監(jiān)聽函數(shù)

// 這里是 ctx  let someVar = ...
document.addEventListener("foo", event => { // 在 document 上綁定 foo 事件的監(jiān)聽函數(shù)
      event.preventDefault()
      // do something ...
    }
}

應(yīng)用:

// 模擬私有變量
function makeIncrement(){
    let __somePrivate = 1;  // 此變量外界無法干預(yù)
    return function(){
        // 有內(nèi)存泄漏嫌疑
        return __somePrivate++;   // 注意前后綴++運算符區(qū)別
    }
}

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

語法迷思

js有很多操作其實都是反直覺的

原型鏈

如果用傳統(tǒng)面向?qū)ο笳Z言類比润努,那么原型鏈是類與類之間的關(guān)系,此處需要區(qū)別類 和實例

領(lǐng)域關(guān)鍵字

arguments
this:
傳統(tǒng)面向?qū)ο笳Z言中的this

class MyObj{
    constructor(name: string){  // 構(gòu)造器
        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綁定

四種綁定方式
遵循以下優(yōu)先級
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 箭頭函數(shù)this

1 不準確的說法
箭頭函數(shù)指向外層
箭頭函數(shù)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()();
// 箭頭函數(shù)this始終指向外層【函數(shù)】所綁定的作用域
// 箭頭函數(shù)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 規(guī)則

this的值在函數(shù)被調(diào)用的時候才會指定

應(yīng)用解答

前置知識

var關(guān)鍵字

1 掛載到window對象
2 變量不經(jīng)申明也掛載到window對象下
坑點: 全局變量污染

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

3 沒有塊級別作用域

if (true){
    var hello = 'world';
}
console.log(hello);
var和let區(qū)別

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 是異步編程的一種解決方案倚聚,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強大。

構(gòu)造函數(shù)

// 主意構(gòu)造方法  比較獨特
const myPromise = new Promise((resolve, reject)=>{
    if (// 異步操作成功)  resolve('success');
    reject('error');
})

// then  方法接收兩個函數(shù) 分別是成功和失敗的處理
myPromise.then(()=> console.log('hello world'))

此時 myPromise 是一個thenable 對象, 且通過then方法返回的也是 promise對象

特點

對象的狀態(tài)不受外界影響凿可。Promise對象代表一個異步操作秉沼,有三種狀態(tài):pending(進行中)、fulfilled(已成功)和rejected(已失斂蠼汀)。
一旦狀態(tài)改變矗积,就不會再變全肮,任何時候都可以得到這個結(jié)果。

實例方法

所有promise 對象的實例方法均會返回promise對象棘捣,從而可以形成調(diào)用鏈

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 方法接收兩個參數(shù)
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 可以處理  構(gòu)造函數(shù)里  reject 拋出的錯誤 
// 也可以處理 resolve或 then 里通用代碼拋出的異常
obj.then(()=>{
    throw new Error('err')
}).catch((e)=>console.log(`catch error ${e}`));

// 此時如果沒有catch 的話則會拋出運行時異常

靜態(tài)方法

Promsie.all

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

Promise.all()方法接受一個數(shù)組作為參數(shù)辜腺,p1、p2乍恐、p3都是 Promise 實例评疗,如果不是,就會先調(diào)用下面講到的Promise.resolve方法茵烈,將參數(shù)轉(zhuǎn)為 Promise 實例百匆,再進一步處理。另外呜投,Promise.all()方法的參數(shù)可以不是數(shù)組加匈,但必須具有 Iterator 接口存璃,且返回的每個成員都是 Promise 實例。

p的狀態(tài)由p1雕拼、p2纵东、p3決定,分成兩種情況啥寇。(1)只有p1偎球、p2、p3的狀態(tài)都變成fulfilled辑甜,p的狀態(tài)才會變成fulfilled衰絮,此時p1、p2栈戳、p3的返回值組成一個數(shù)組岂傲,傳遞給p的回調(diào)函數(shù)。(2)只要p1子檀、p2镊掖、p3之中有一個被rejected,p的狀態(tài)就變成rejected褂痰,此時第一個被reject的實例的返回值亩进,會傳遞給p的回調(diào)函數(shù)。

Promise.race

Promise.allSettled

Promise.resolve

Promise.resolve('foo')
// 等價于
new Promise(resolve => resolve('foo'))
// resolve方法相當于一個快捷方式  

resolve的參數(shù):
1 promise對象則原封不動返回
2 thenable 對象則立即執(zhí)行then方法然后返回結(jié)果對象的promise包裝
3 其他則包裝參數(shù)中內(nèi)容為 resolve狀態(tài)的promise對象

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

Promise.reject

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末缩歪,一起剝皮案震驚了整個濱河市归薛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌匪蝙,老刑警劉巖主籍,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異逛球,居然都是意外死亡千元,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門颤绕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來幸海,“玉大人,你說我怎么就攤上這事奥务∥锒溃” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵氯葬,是天一觀的道長挡篓。 經(jīng)常有香客問我,道長帚称,這世上最難降的妖魔是什么瞻凤? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任憨攒,我火速辦了婚禮,結(jié)果婚禮上阀参,老公的妹妹穿的比我還像新娘肝集。我一直安慰自己,他們只是感情好蛛壳,可當我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布杏瞻。 她就那樣靜靜地躺著,像睡著了一般衙荐。 火紅的嫁衣襯著肌膚如雪捞挥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天忧吟,我揣著相機與錄音砌函,去河邊找鬼。 笑死溜族,一個胖子當著我的面吹牛讹俊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播煌抒,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼仍劈,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了寡壮?” 一聲冷哼從身側(cè)響起贩疙,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎况既,沒想到半個月后这溅,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡棒仍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年芍躏,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片降狠。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖庇楞,靈堂內(nèi)的尸體忽然破棺而出榜配,到底是詐尸還是另有隱情,我是刑警寧澤吕晌,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布蛋褥,位于F島的核電站,受9級特大地震影響睛驳,放射性物質(zhì)發(fā)生泄漏烙心。R本人自食惡果不足惜膜廊,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望淫茵。 院中可真熱鬧爪瓜,春花似錦、人聲如沸匙瘪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽丹喻。三九已至薄货,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間碍论,已是汗流浹背谅猾。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留鳍悠,地道東北人税娜。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像贼涩,于是被迫代替她去往敵國和親巧涧。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 背景 1995 年 Netscape 公司的 Brendan Eich 創(chuàng)造了 Javascript遥倦。 1996 ...
    紫山坡下閱讀 253評論 0 0
  • 入門與進階 第一章 進入編程 1谤绳,如何快速運行一段js代碼? 方式1:瀏覽器開發(fā)者工具袒哥∷跎福可以使用快捷鍵option...
    瀟瀟瀟瀟瀟瀟瀟閱讀 871評論 0 0
  • 1. JS創(chuàng)建變量的5種方式?varletconstfunctionexport/import 2. var堡称,le...
    Angel_6c4e閱讀 821評論 0 13
  • 1.事件冒泡與事件捕獲 事件冒泡:由最具體的元素(目標元素)向外傳播到最不具體的元素事件捕獲:由最不確定的元素到目...
    吃肉肉不吃肉肉閱讀 200評論 0 1
  • 1.自執(zhí)行函數(shù)?用于什么場景瞎抛?好處? 自執(zhí)行函數(shù):1、聲明一個匿名函數(shù)2却紧、馬上調(diào)用這個匿名函數(shù)桐臊。作用:創(chuàng)建一個獨立...
    一只小丫丫閱讀 174評論 0 0