摘要:上下文切換上下文最直觀的表現就是代碼塊中的,通常在面向對象的編程中用到,來指代當前類生成的對應實例,與其他語言的一致。咦,是干嘛的,有沒有其他方式實現,請自行谷歌。
分享第一篇,關于 NodeJS —— Javascript 的常用知識以及如何從 Javascript 開發者過渡到 NodeJS 開發者(不會介紹具體的框架)。在讀本文前,希望你對 javascript 有一些初步的認識。
Javascript 是一門原型模型的解釋型語言。解釋型將在后面的 NodeJS 里面討論,原型鏈是 ES6 之前的 Javascript 的面向對象的實現方式之一,在 ES6 中支持的 class 增加了一種新的實現方式。在 Javascript 里面所有東西都是對象,包括 “類”。接觸過 ruby/python 的元編程的可能會覺得這個很熟悉,Javascript 也很容易是實現出動態的生成類的方法。
1. 基于原型鏈實現的簡單的“類”javascriptvar Person = function(name){ this.name = name; }; Person.staticSay = function(name){ console.log("Hello " + name); }; Person.prototype.sayHi = function(){ Person.staticSay(this.name); }
提一些常見的規范,例如 Javascript 中所有的方法都是駝峰命名,優先使用單引號,兩個空格等等,更多的規范可以參考 https://github.com/airbnb/javascript。
代碼中的staticSay為靜態方法,即只能通過 Person.staticSay來調用。 當上面的 Person 生成實例的時候,例如 var vincent = new Person("vincent");的時候,vincent會自動繼承 Person.prototype 的所有方法(代碼中的 this 指代的是當前上下文,即上文中的 vincent)。
同時也可以動態的為對象 vincent 添加方法,例如如下代碼:
javascriptvar vincent = new Person("vincent") vincent.tellName = function(){ console.log("Hi, i"m am" + this.name) };
然后當你需要模擬繼承的時候,就需要在 prototype 上下功夫。例如下面使用 Worker.prototype = new Person() 來實現,new Person() 返回的實例對象帶著的所有方法、屬性都被賦給了 prototype,變相模擬了繼承。這種方式最終一層層的往上找 prototype 里面的內容(因為每個實例具有的方法都在 prototype 里面,往上直到 Object)。當然也可以通過遍歷來進行對 prototype 賦值來模擬繼承。
2. 上下文切換上下文最直觀的表現就是代碼塊中的 this,通常在面向對象的編程中用到,來指代當前“類”生成的對應實例,與其他語言的 self一致。
繼續用上文中的例子,上文中已經實現了一個 Person.prototype.sayHi方法,現在我有一個新的對象,代碼如下:
javascriptvar Cat = function(name){ this.name = name; } var c = new Cat("tomcat");
如果某天突然異想天開希望這只貓像人一樣介紹他自己怎么辦,他自己沒有 sayHi 這個方法。但是可以通過 console.log(Person.prototype.sayHi)是可以拿到人類的 sayHi 方法的,怎么讓貓也可以使用呢?
Javascript 有兩個方法,call 和 apply,他們的區別就是參數不同(自行谷歌),作用是用來切換上下文。簡單說就是可以把 Person.prototype.sayHi這個函數中的 this 變成其他對象。使用方式: Person.prototype.sayHi.call(c)。
這個實用嘛?例如如下場景:
javascriptvar doSomething = function(){ var persons = arguments; };
上面的函數中,通過關鍵字 arguments獲取所有的參數來支持不定數量的參數。現在我們希望對 persons用一些原屬于 Array 類型的方法,如何實現呢?這里就可以用上下文切換來實現:
javascriptvar doSomething = function(){ var persons = arguments; // 使用 Array 的 slice 方法,將 arguments 對象轉變為 Array 實例 var persons_arr = Array.prototype.slice.call(arguments); };3. 閉包
先來段常見的代碼
javascriptfor (var i = 0; i < 3; i ++){ setTimeout(function(){ console.log(i); }, i) }
這個會輸出什么結果呢?依次輸出 0 1 2 ?實際情況是,當 setTimeout第一次執行回調的時候,for 循環已經結束了,也就是說此時的 i 已經是 3 了,導致最終的輸出結果是 3 3 3。
當你需要保護某一個變量,使得他不被外圍的代碼所影響的時候,你可能就需要考慮下閉包 —— 一個封閉的作用域的代碼塊。
javascriptfor (var i = 0; i < 3; i ++){ +function(i){ setTimeout(function(){ console.log(i); }, i) }(i) }
咦, +是干嘛的,有沒有其他方式實現,請自行谷歌。閉包內的 i 的作用域是一個封閉的作用域,所以最終 閉包內的 i 一直沒有被外面的執行改變,所以可以成功的輸出 0 1 2。
簡單的介紹了 javascript 部分特性,關鍵字 原型鏈、call 和 apply、arguments 關鍵字,更多的建議可以看看例如權威指南這樣的書,或者快速了解下基本的類型以及每個類型有的方法。有一些比較神奇的代碼,例如獲得當前的代碼的字符串,然后進行處理得到自己想要的內容,使用 getter 和 setter 在用戶對對象屬性獲取或者賦值的時候做一些特殊的操作等等。
4. NodeJS 和 Javascript 的開發區別這塊主要介紹 require 加載的基礎知識,首先先介紹一些代碼:
javascript// a.js module.exports = { name: "a", doSomething: function(){ return "something"; } } // b.js var a = require("./a") global.a_name = a.name; // c.js require("./b"); console.log(a_name) // 執行后打印 a
當我們執行 node c.js的時候發生了什么?
require是 nodes 關鍵字,雖然 NodeJS 是以異步著稱,但是他的 require都是阻塞的。否則就會出現還沒有載入其他模塊,已經開始執行下面的代碼的情況。
require.resolve()方法是用來找出你所引用的文件的實際路徑,找出后 Nodejs 會在 require.cache里面尋找是否有緩存,沒有的話則會讀取文件然后解析,所以通常情況下,一個 js 文件里面的執行的代碼只會在第一次被 require 的時候被執行。(tip. require.cache 如果有需要的話是可以手動刪除一些東西的,然后可以某種程度上可以執行多次)
當 b.js 開始執行的時候,他需要先載入 a.js,module.exports告訴 Nodejs 這個文件對外暴露寫什么,例如 a.js 暴露的是一個對象,包含 name 屬性和 doSomething 方法。然后 b.js 中的 a 變量其實就是這個對象。
執行完獲取 a.js 后,繼續回到 b.js ,global.a_name 相當于聲明了一個全局變量,這個和前端中的 window.a_name = a.name 效果類似。
最終過程完成,c.js 執行輸出值。
5. 異步的底層原理NodeJS 很容易給人一種使用上的錯覺,就是寫了很久都可能不知道底層的異步是怎么實現的。(下面的理解主要來自于對 python3.4 中的 asyncio 的理解,如有錯誤歡迎指出)。
NodeJS 底層的 libev 分別在 Window 下使用 IOCP 和 *nix 下使用基于 AIO 的 libeio 來實現異步。通過系統層面的技術,最后達到一個目的,就是應用程序發起一個異步請求,最終在系統執行完后,系統通知應用程序處理完成。在這個過程中,應用程序可以將之前的處理掛起/推入線程池中等待執行,而應用程序在此期間可以執行其他任務。
整個的運行通過系統層面的事件循環來進行運作。例如 Python 提供了類似于 run_until 以及 run_forever 的這樣的方法,保證在異步執行之前程序不會結束運行。將整個異步想象成一個一直在運作的車間,車間里面的機器負責查看包裹并蓋章這樣的操作,工人拿到了一個包裹,然后貼上相應的標簽后放進去,等車間處理完后再交還給工人,工人根據包裹上他之前貼上的標簽和被車間貼上的標簽,進行下一步的處理。工人無需等待包裹檢查完畢才能進行下一個,他只需要接受簡單處理,然后放入車間進行檢查。然后等某個時間車間返回給他某個包裹,他再去進行下一步的操作。
目前主要還是只介紹了一些語言層面的知識,但是只有這些距離開發一個完整的 web 還有一些距離,將在后面繼續介紹。包括 Redis,Nginx,測試驅動等等。
原文:https://github.com/vincenting/note/issues/1
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/91497.html
摘要:最近利用空閑時間寫了一個從入門到上線的的實戰教程從入門到上線目前還在更新中,入門篇已基本成型。本項目使用語法,采用搭建了一個博客系統,實現了文章管理用戶登錄注冊權限控制分類管理等功能。實現線上部署左手代碼右手磚拋磚引玉 最近利用空閑時間寫了一個從入門到上線的的node實戰教程《Node.js從入門到上線》A blog build with Koa2. 目前還在更新中,入門篇已基本成型。...
摘要:新手篇入門基礎教程關于的分享此前一直都是零零散散的想到什么就寫什么,整體寫的比較亂吧。上兩周寫的五篇內容,匯總到一起就算是新手入門的一個基礎性教程吧持續更新中。應該在改版完成后就可以正常申請下載了。 Hadoop新手篇:hadoop入門基礎教程關于hadoop的分享此前一直都是零零散散的想到什么就寫什么,整體寫的比較亂吧。最近可能還算好的吧,畢竟花了兩周的時間詳細的寫完的了hadoop...
摘要:個人前端文章整理從最開始萌生寫文章的想法,到著手開始寫,再到現在已經一年的時間了,由于工作比較忙,更新緩慢,后面還是會繼更新,現將已經寫好的文章整理一個目錄,方便更多的小伙伴去學習。 showImg(https://segmentfault.com/img/remote/1460000017490740?w=1920&h=1080); 個人前端文章整理 從最開始萌生寫文章的想法,到著手...
新編html網頁設計從入門到精通共分為21章,全面系統地講解了html的發展歷史及4.0版的新特性、基本概念、設計原則、文件結構、文件屬性標記、用格式標記進行頁面排版、使用圖像裝飾頁面、超鏈接的使用、使用表格組織頁面、使用多媒體美化頁面、創建多框架頁面、動態網頁的制作、使用層疊樣式表(css)美化頁面、javascript語言、數組和字符串以及表達式與程序的流程控制等內容。 本書適合作為培訓學校的...
閱讀 1673·2021-11-15 11:38
閱讀 4514·2021-09-22 15:33
閱讀 2332·2021-08-30 09:46
閱讀 2176·2019-08-30 15:43
閱讀 827·2019-08-30 14:16
閱讀 2069·2019-08-30 13:09
閱讀 1255·2019-08-30 11:25
閱讀 701·2019-08-29 16:42