全栈必备 JavaScript基础

JavaScript 来了


1995年。诞生了JavaScript语言,那一年,我刚刚从大学毕业。在今年RedMonk 推出的2017 年第一季度编程语言排行榜中。JavaScript 排第一,Java 第二,Python 反超 PHP 排第三。PHP 第四,C# 和 C++ 并列第五。RedMonk 排名的主要依然是各类编程语言在 Stack Overflow 和 GitHub 上的表现,比方编程语言在 Stack Overflow 上的讨论数量,在 GitHub 上的代码量等。虽然有必定的片面性。仍是说明了JavaScript 应用的普遍性。从全栈的角度看,Javascript 是必备的一种编程语言。javascript

 


ECMAScript 和 JavaScript 的关系

JavaScript 诞生于Netscape,但是在1996年。微软公布了与JavaScript 兼容的JScript,面对兼容和发展的需要。网景公司的先贤们努力增长了 ECMA International 标准化组织,致力于JavaScript 的标准化,命名为ECMAScript。后来,由于历史的缘由, JavaScript标准的开发主体变成了Mozila基金会。css

关于ECMAScript 的最新版本号可以參阅 https://tc39.github.io/ecma262/。html

简单地,ECMAScript 是JavaScript语言的标准规范。就像C++的标准相对于C++语言那样。前端

JavaScript 是怎样的语言

在mozilla 开发人员站点上是这样描写叙述JavaScript的:java

JavaScript (JS) is a lightweight interpreted or JIT-compiled programming language with first-class functions. node

意思是说JavaScript 是一个轻量级解释或即时编译的函数式语言。里面有很是多的概念,轻量、解释、编译、即时编译、函数式。git

在老码农看来,简单起见,理解为扩展语言较为方便。github

通常的编程语言都有着本身相对独立的运行环境。但是JavaScript的运行环境依赖在宿主环境中。宿主环境尤为是client的宿主环境提供了不少其它统一的环境变量,比方浏览器中的window。document等。实际上,JavaScript 和DOM 是可分的,对于不一样的运行环境,有着不一样的内置宿主对象。web

JavaScript做为扩展语言在内置的宿主环境中运行,全局对象在程序启动前就已经存在了。shell

JavaScript的时空基础

从空间观的角度看。JavaScript包含数据结构,操做符,语句与表达式。函数。从时间的角度看,包含做用域,处理方式,模块与库。关于技术系统的时空观,可以參见《面向全栈的技术管理》一文。

数据结构

JavaScript 中包含的六种基本类型:

  • Boolean

  • Null

  • Undefined

  • Number

  • String

  • Symbol (ECMAScript 6)

其它全是对象。

值是有类型的。变量是没有类型的,类型定义了值的行为特征,变量在没有持有值的时候是undefined。 JavaScript对值和引用的赋值/传递在语法上没有差异,全然依据值的类型来断定。

对于对象的属性和方法而言,全局变量和全局函数是全局对象的属性。全局对象至关于宿主对象的根对象。需要注意是属性的属性中那些不可变对象的实现方式: 

  1. 对象常量: 结合writable和configurable:false 可以建立一个真正的常量属性

  2. 禁止扩张:Object.preventExtensions(..)来禁止一个对象增长新属性并保留已有属性

  3. 密封: 在 Object.seal(..) 后不能增,删,改 该属性

  4. 冻结: Object.freeze(..) 会禁止对于对象自己及随意直接属性的改动

数据类型的断定可以经过 contructor,instanceof。 isPrototypeOf等方法实现,对于鸭子类型的断定还可以使用 in 的相关操做。符号并不是对象,而是一种简单标量基本类型。

 JavaScript 中的强制类型转换老是返回基本类型值,将对象强制转换为String 是经过ToPrimitive抽象操做完毕的。而toJSON()是返回一个可以被字符串化的安全的JSON值。

操做符

操做符是空间元素链接的纽带之中的一个,JavaScript操做符包含算术,链接,相等。比較。逻辑,位。类型推断。条件。new,delete, void,"。", ".", "[]"等。

在JavaScript中以操做符进行操做每每都附带着类型转换。

一元运算符+ 是显式强制类型转换,而~是先转换为32位数字,而后按位反转。

|| 和&& 更应该算是选择器运算符。其返回值不必定是布尔值,而是两个操做数当中的一个值。通常先对第一个操做数进行toBoolean强制类型转换,而后再运行条件推断。好比:a||b 理解成a?a:b 更通俗。对&& 而言,假设第一个是真值。则把第二个做为返回值。a&&b 理解成a?

b:a 。

== 和=== 都会对操做数进行类型检查。并运行隐性类型转换,需要注意的是: 

  • 假设两边的值中有true或false,千万不要使用==

  • 假设两边有[],””或者0。尽可能不要使用==

这里是Github上关于各类相等性的矩阵: 


语句与表达式

操做符与变量/常量等链接造成了语句和表达式,好比表达式a+1中的null 被强制转换为0。

语句包含声明与块,控制语句有推断。循环。break。continue,return,异常等。每个语句都有一个结果值。哪怕是undefined。

正則表達式是很是重要的一类表达式。主要使用RegExp类,运行方法test效率高,exec 会获得一个结果对象的数组。

逗号运算符可以把多个独立的表达式串联成一个语句,{ }在不一样状况下的意思不尽相同,做为语句块,{ ..} 和for/while循环以及if条件语句中代码块的做用基本相同。

{a,b} 其实是{a:a,b:b}的简化版本号。

try..catch..finally 中,假设finally中抛出异常。函数会在此处终止。需要注意的是,假设此前try中已经有return设置了返回值,则该值会被丢弃。finally中的return也会覆盖try和catch中的return的返回值。

函数与做用域

函数就是具备运算逻辑的对象,匿名函数不利于调试,回调函数是一种控制反转。所有的函数(对象)都具备名为prototype的属性,prototype属性引用的对象是prototype对象;所有的对象都含有一个隐式连接,用以指向在对象生成过程当中所使用的构造函数的prototype对象。

匿名函数没有name 标识符,具备例如如下缺陷: 

  1. 代码更难理解

  2. 调试栈更难追踪

  3. 自我引用(递归,事件(解除)绑定,等)更难

假设function是声明的第一个词,那就是函数声明,不然就是函数表达式。立刻运行函数表达式形如:(function …)( )

时空密不可分,做用域是时空链接的纽带之中的一个。做用域包含全局,函数。块级做用域。做用域是依据名称查找变量的一套规则。遍历嵌套做用域链的规则简单:引擎从当前运行做用域逐级向上查找。闭包可以理解为具备状态的函数。

函数做用域指属于这个函数的所有变量都可以在整个函数的范围内使用或复用。块做用域形如 with。 try/catch。 ES6 引入了let,const等。

动态做用域并不关心函数和做用域是怎样声明以及在何处声明的,仅仅关心它们从何处调用的。词法做用域是定义在词法分析阶段的做用域。词法做用域查找会在第一个匹配的标识符时中止。

做用域链是基于调用栈的。而不是代码中的做用域嵌套。ReferenceError 是与做用域判别失败相关。而TypeError则是做用域判别成功,但是对结果的操做非法或不合理。

this 提供了一种优雅方式来隐式“传递”一个对象引用。 this 即没有指向函数的自身,也没有指向函数的做用域。是在函数被调用时发生的绑定,它指向什么全然取决于函数在哪里被调用。假设分析this绑定的话,可以使用调试工具获得调用栈。而后找到栈中的第二个元素,就是真正的调用位置。

this 的绑定规则有:

  1. 默认绑定:独立的函数调用,严格模式不能将全局对象用于默认绑定

  2. 隐式绑定:把函数调用中的this 绑定到函数引用中的上下文对象

  3. 显式绑定:经过call()和apply()方法可以直接指定this的绑定对象。

    当中,硬绑定是一种显式的强制绑定,ES5中提供了内置方法Function.prototype.bind, API中调用的上下文和bind的做用同样。

  4. new 绑定,构造函数仅仅是一些使用new操做符调用的函, 使用new 来调用函数的操做过程大体例如如下:

  • 建立一个全新的对象

  • 这个新对象会被运行[[Prototype]]连接

  • 这个新对象会绑定到函数调用的this

  • 假设函数没有返回其它对象,那么new表达式中的函数调用会本身主动返回这个新对象

假设同一时候存在多种绑定。那么绑定的优先级大体例如如下:

  1. 由new调用绑定到新建立的对象

  2. 由call 或者apply(或bind)调用绑定到指定的对象

  3. 由上下文对象调用绑定到那个上下文对象

  4. 默认在在严格模式下绑定到undefined,不然绑定到全局对象

更安全地使用this 绑定的作法是传入一个特殊的对象,把this 绑定到这个对象。需要注意的是。箭头函数不使用this的4种规则,而是依据外层(函数或全局)做用域来决定this。

还要注意一点,eval 和 with 会致使做用域变化而引发性能降低,尽可能不要使用。

eval() 函数中的字符串是代码,用来运行动态建立的代码,严格模式有本身的做用域,还存在安全隐患;with 是反复引用一个对象中的多个属性的快捷方式,经过将一个对象的引用看成做用域来处理,会改变做用域范围。

处理和运行方式

JavaScript引擎自己没有时间概念。仅仅是一个按需运行随意代码片断的环境,事件调度老是由包含它的宿主环境来运行。一旦有事件需要运行,事件循环队列就会运行。直到队列清空,用户交互、IO和定时器等事件源会向事件队列增长事件。

由于JavaScript的单线程特性,很是多函数的代码具备原子性。

回调函数封装了程序的延续性,常见设计是分离回调(一个用于成功通知,一个用于出错通知)。还有一种回调模式是“error-first”,可能受到防护式编程的影响,NodeJS API 採用了此类的风格。假设成功的话,这个參数就会被清空。需要注意的是,回调函数的嵌套每每称为回调地狱。

Deferred是一种将异步处理串联书写并运行的机制,Deferred对象是一种具备unresolved,resolved,rejected 中某一种状态的对象。

Deferred内部机制是先注冊回调函数,Deferred对象状态发生变化时运行该函数。是一种提升代码可读性的机制。

Deferred对象的状态迁移仅仅能发生一次,以then(),done(),fail(),always(),pipe()指定兴许函数的方法。经过when()来并行处理,将Deferred 对象中的一部分方法删除后获得是Promise对象,对状态的管理由最初建立该Deferred对象的所有者来运行。

Promise 封装了依赖于时间的状态,从而使得自己与时间无关。Promise 可以依照可预測的方式进行,而不用关心时序或底层的结果。一旦Promise决议完毕。就成为了避免变值,可以安全地吧这个值传递给第三方,并确保不会改变。

Promise 是一种在异步任务中做为两个或不少其它步骤的流程控制机制,时序上的this-then-that。 不只表达了多步异步序列的流程控制。仍是一个从一个步骤到下一个步骤传递消息的消息通道。事件监听对象可以当成是对promise 的一种模拟,对控制反转的恢复实现了更好的关注点分离。

推断是不是Promise 值的演示样例代码例如如下:

if(
    p !==null &&
    ( typeof p ===“object” || typeof p ===“function”) && typeof p.then===“function”)
    {
        console.log(“thenable”);
    }
else{
    console.log(“not thenable”);
}

生成器是一类特殊的函数。可以一次或屡次启动和中止,并不非的必定要完毕,生成器把while true 带回了Javascript的世界。

当中,yield 托付的主要目的是代码组织,以达到与普通函数调用的对称。从生成器yield出一个Promise, 而且让这个Promise 经过一个辅助函数恢复这个生成器。这是经过生成器管理异步的好方法之中的一个。 

需要注意的是,假设在Promise.all([..]) 中传入空数组,会立刻完毕, 而Promise.race([..]) 则会挂住。 在各类Promise库中,finally ( .. ) 仍是会建立并返回一个新Promise的。

模块与库

模块和库是JavaScript 时空中的还有一纽带。提升了代码的复用性和开发效率。

模块充分利用了闭包的强大能力。从模块中返回一个实际的对象并不是必须的。也可以直接返回一个内部函数,好比:jQauery 和 $标识符就是jQuery 模块的公共API。

模块有两个必要条件: 

  1. 必须有外部的封闭函数。该函数必须至少被调用一次 

  2. 封闭函数必须返回至少一个内部函数,这样内部函数才干在私有做用域中造成闭包,而且可以訪问或改动私有的状态

import 可以将一个模块的一个或多个API导入到当前做用域中。并分别绑定在一个变量上;module 则将整个模块的API 导入并绑定到一个变量上, export 将当前模块的一个标识符导出为公共API。

大多数模块所依赖的加载器/管理器本质上是将这种模块定义封装进一个API。基于函数的模块并不是一个能被静态识别的模式(编译器),API定义仅仅有在运行时考虑进来。

但是ES6 模块的API 是静态的,必须被定义在独立的文件里。

JavaScript 中的库浩如烟海,这里仅对JQuery作简要说明。JQuery压缩后大约31k,轻巧灵活,经过链式语法实现逻辑功能。经过CSS3选择器及本身定义选择器获取元素,支持插件。可扩展性高。

JQuery中 的特点函数——$ ,可以抽取与选择器匹配的元素,或者建立新的DOM元素,将已有的DOM元素转换为jQuery对象,对DOM构造完毕后的事件监听器进行设定等等。JQuery 对DOM,样式,AJAX 都可有效处理。

经过扩展JQuery.fn 就可以建立JQuery的插件,code.google.com/apis/libraries 给出了很是多JQuery 的插件信息。

利用JavaScript 的时空观,可以对这一语言有一些主要的梳理。就语言自己而言。keyword是不能回避的,对JavaScript keyword,在StackOverFlow中有人给出了例如如下诗同样的总结:

Let this long package float, Goto private class if short。 While protected with debug case, Continue volatile interface。

Instanceof super synchronized throw。 Extends final export throws. Try import double enum?

-False, boolean, abstract function. Implements typeof transient break! Void static,default do, Switch int native new, else, delete null public var, In return for const, true, char, …… finally catch byte.

client应用

一门语言所被使用的普遍程度取决于使用的场景,正如PHP被普遍採用那样,互联网应用不只是JavaScript 的家乡,而且是它大展身手的最重要场所,没有JavaScript 的Web应用差点儿绝迹了。

web应用中使用JavaScript有拖拽操做。异步读取。键盘訪问 和动画效果等基本功能。对于清晰地使用JavaScript实现Web应用而言。理解浏览器网页处理过程是必要的。

通常地,浏览器先分析HTML。而后构造DOM树。再加载外部Javascript 文件以及CSS文件,接下来加载图像文件等外部资源。最后在分析Javascript后開始运行至所有完毕。

在HTML中加载JavaScript的方式有多种:

  • <script> 标签。在body 结束标签前写

  • 读取外部JavaScript 文件,读取完就開始运行,浏览器可以缓存

  • onload 事件加载

  • DOMContentLoaded是在完毕HTML解析后发生的事件,也可以用于加载JavaScript

  • 动态加载。这样JS在加载时不会阻断其它操做,如

    var script = document.createElement(‘script’);

    script.src = ‘my-javascript.js’;

    document.getElementsByTagName(‘head’)[0].appendChild(script)

window对象是JavaScript所能操做的最高层对象,当中的属性包含navigator,location,history,screen,frames。document,parent,top。self 等。

DOM 是一种API。完毕对HTML/XML 的树形结构訪问。如标签,元素。节点等。节点可以经过ID。标签名。名称和类名进行检索。好比:

var element = document.getElementById(“abel”)
var allelements = document.getElementByTagName(‘*’)

由于返回的是NodeList对象,性能较差。可以经过 var array = Array.prototye.slice.call(allelements)转换为array 后处理。

节点的訪问可以经过XPath 进行灵活的訪问,固然,Selector API 比XPath更简单且相同灵活。好比:

var a_label = document.querySelector(‘#abel’)
var b_all = document.querySelectorAll(‘div’)

假设先改动DocumentFragment。再对实际的document对象操做。DOM 的操做性能会较高一些。

事件侦听器的设定可以制定HTML元素的属性。也可以指定DOM元素的属性。还可以经过EventTarget.addEventListenser()进行指定。事件的处理包含捕获。目标处理和事件冒泡三个阶段。捕获的过程是:

window -> document -> html -> body -> div -> button  

而后处理器运行,冒泡向上传播的过程是遍历DOM树,需要注意的是 focus 不会冒泡。

DOM2中的标准事件有HTMLEvent,MouseEvent。UIEvent和MutationEvent。DOM3 中的事件不少其它:UIEvent,FocusEvent,MouseEvent, WheelEvent, TextEvent,KeyboardEvent 和compositionEvent等,还可以通document.createEvent来本身定义事件。

经过JavaScript 对CSS样式变动的方法有经过className 属性变动class名,经过classList属性更改class名(当中classList 是H5对DOM TokenList接口的实现),还可以更改Style 属性或者直接更改样式表。经过JavaScript可以对屏幕位置(screenX。screenY),窗体位置(clientX,clientY)。文档坐标(pageX。pageY。由浏览器自行实现的),特定元素内的相对位置(layerX,layerY 或offsetX offsetY)进行改动。

经过JavaScript可以对表单中的元素,控件和内容进行验证,可用于验证的事件有submit,focus。blur,change,keydown/up/press。input。使用表单而不产生页面跳转的方式可以是指向到一个 (0,0 )的空iframe。

对于动画而言。css的动画性能通常要更好一些。

AJAX 在Web应用中是不可或缺的。简单地说,是一种不发生页面跳转就能异步加载内容并改写页面内容的技术。主要经过 XMLHttpRequest 对象的建立,实现通/异步通讯,处理超时和响应。AJAX有着跨源限制,实现跨源通讯的方式有:JSONP。iframe hack,window.postMessage() 以及 XMLHttpRequest Level 2。

HTML5+CSS3+JavaScript的综合使用才可能成就一个Web应用。

H5中的 History API 使用了window属性的history对象监听popstate事件。用于恢复页面状态的处理。ApplicationCache 在html标签的manifest 属性中指定了缓存清单文件的路径,必须经过text/cache-manifest 这一MIME type 来公布缓存清单文件。注意清单中的CACHE,NETWORK,和FALLBACK 的区分。

经过navigator.onLine 可以获知网络状态,还可以经过online/offline事件来侦听链接状态的切换时机。

online/offline事件是document.body 触发的,并传给document对象和window对象。

<p> network is : <span id = “indicator”> (state unknown) </span> </p>
<script>
{
    function updateIndicator = document.getElementById(‘indicator’);
    indicator.textContext = navigator.online?’online’:’offline’;
}
document.body.onload = updateIndicator;
document.body.ononline= updateIndicator;
document.body.onoffline = updateIndicator;
</script>

DataTransfer 是Drag Drop API 的核心,在所有拖拽事件的事件对象中,都有该属性,主要是接收数据。

拖拽文件从浏览器保存到桌面:event.dataTransfer.setData(‘DownloadURL’,’MIMETYPE: 文件url’)好比:

   <a href=“http://a.b.c/abel.pdf” 
    data-downloadurl = “application/pdf:abel.pdf:http://a.b.c/abel.pdf”
    class=“dragout” draggable = “true”>download </a>
    <script>
    var files = document.querySelectorAll(‘.dragout’);
    for (var i = 0,file; file =files[i];i++) {
        file.addEventListener(‘dragstart’,function(event){
    event.dataTransfer.setData(“DownloadURL”,this.dataset.downloadurl);
    },false);
    }
    </script>

FileAPI 经过FileReader 读取文件,也可以读取dataURL。FileReaderSync 用于同步读取文件内容,可以在Web Worker 中使用。

Web Storage 为所有源共享5M空间。localStorage 和sessionStorage 的差异在于数据的生命周期。cookie 最大4k,发请求时一块儿发送,保存会话等重要信息。

indexedDB 可以归为文档型数据库, 做为client存储又一选择。

var indexdb = window.indexDB||window.webkitIndexedDB||window.mozIndexedDB;

Web worker 是H5 的新特性,是宿主环境(浏览器)的功能,JavaScript 自己是不支持多线程的。专用的worker 与建立它的程序之间是一对一的关系。

Web worker 能在另外的线程中建立新的Javascript 运行环境,使JavaScripts可以在后台处理。主线程和工做线程分离。没法使用对方环境的变量。工做线程没法引用document对象,需要经过消息收发完毕数据传递。 在主线程建立工做线程。大约向var worker = new Worker(‘work.js’)这样 在主线程中中止worker的方式是worker.terminate(); worker 自身中止的方式是 self.close();worker 中 可以通个 importScripts 方法,在工做线程内读取外部的文件。

了解了这些基础方式和方法,仅仅是Web应用中JavaScript开发的第一步吧。

服务端应用

技术系统老是又着向超系统进化的趋势。JavaScript 也不例外。

JavaScript 应用于服务端的开发源于2009年初出现的CommonJS,后来成为为了server端javaScript的规范。基于JavaScript没有模块系统、标准库较少、缺少包管理工具等现状,CommonJS规范但愿JavaScript可以在不论什么地方运行,以达到Java、C#、PHP这些后台语言具有开发大型应用的能力。

CommonJS是一种思想,它的终极目标是使应用程序开发人员依据CommonJS API编写的JavaScript应用可以在不一样的JavaScript解析器和HOST环境上运行。好比编写服务端应用。命令行工具。基于GUI的桌面应用和混合应用编程等,详情參加 www.commonjs.org 。

NodeJS可以理解成CommonJS规范的一种实现。而且是部分实现。NodeJS以V8做为JavaScript的实现引擎,通用的异步处理事件循环,提供了一系列非堵塞函数库来支持实践循环特性。同一时候。NodeJS提供了高度优化的应用库。来提升server效率,好比其http 模块是为高速非堵塞式http服务而用C语言重写的。另外,NodeJS还有shell的命令行工具,经过包系统实现扩展,扩展列表可以详情參见: GitHub.com/node/wiki/modules。

JavaScript 中的主要实现引擎包含:IE採用的JScript,Firefox採用的SpiderMoneky。Chrome 採用的V8,Safari採用的webkit中的 javacriptcore灯。假设要对引擎有进一步的了解,可以研读一下javascriptcore等相关的源码。

V8 是NodeJS 中的核心引擎。NodeJS的系统架构大体例如如下:


与浏览器相相应。Node 中的全局变量可以经过 Object.keys(global); 得到。 看一看NodeJS中的 “hello world” 程序:

var http = require('http');
http.createServer(function (req,res){
    res.writeHead(200,{'Content-type':'text/plain'});
    res.end('Hello Node.js \n');
}).listen(1234,"127.0.0.1");
console.log('Server running on http://127.0.0.1:1234/');

几行代码就实现一个简单web server。 使Pythoner 们联想到了 Tornado, 它们都走在单线程异步IO的路上。

NodeJS 提供了对https 的支持,可以经过openssl 生成证书的方式大体是:

openssl req  -new -x509 -keyout key.pen -out cert.perm

使用证书的示比例如如下:

var fs  =require(‘fs’);
var options = {
    key: fs.readFileSync(‘key.perm’);
    cert:fs.readFileSync(‘cert.perm’);
}

NodeJS支持socket 和文件处理,配合系统扩展可以使用各类模版语言。

基于NodeJS的实际在业界很是普遍,比方面向websocket的IM系统,各类web应用站点等等。

鉴于微服务架构的兴起。也诞生了基于Node的微服务架构——Seneca。它使用完备的模式匹配接口来链接各个服务,从代码中将传输数据抽象出来。使编写具备高扩展性的软件变得至关easy。

Seneca 没有使用依赖注入,但是在处理控制反转上至关灵活,没有keyword和强制的字段。仅仅需一组键值对。用于模式匹配的引擎中。详细參考实现,可以參考《node.js 微服务》一书。

基于JavaScript的全栈

假设在整个应用系统中主要使用JavaScript编程语言做为技术栈,那么也可以成为基于JavaScript 的全栈,关于全栈的论述可以參加《全栈的技术栈设想》和《再谈< 全栈架构师>》两篇文字。

好比MEAN架构。即MongoDB + Express + Angular + Node,MEAN 技术栈表明着一种全然现代的 Web 开发方法:一种语言运行在应用程序的所有层次上,从client到server,再到持久层。

借助JavaScript的測试框架。比方MochaJSJasmineJS 和 KarmaJS,可以为本身的 MEAN 应用程序编写深刻而又全面的測试套件,说MEAN有代替LAMP/LNMP的的趋势。但还需保持慎重。

引擎的差别

正像Java 那样。虽然又着虚拟机规范。但各个JVM的实现仍是有着些许的不一样,JavaScript 也是如此。JavaScript各引擎中相同存在着少许的限制,好比:

  • 字符串常量中赞成的最大字符数

  • 做为參数传递到函数中的数据大小(栈大小)

  • 函数声明中的參数个数

  • 函数调用链的最大长度

  • 以堵塞方式在浏览器中运行的最大时间

  • 变量名的最大长度

虽然如此,JavaScript 在浏览器中的表现仍是基本上可信的。

从软件到硬件

实际上,JavaScript已经嵌入到了从机器人到各类家电等各类各样的设备中。这里隆重推荐我很是敬佩的好友——周爱民老师,他在Ruff(南潮信息科技)作的事情就是JavaScript 在物联网上的进一步应用。

Ruff 是一个可以让开发人员实现敏捷开发智能硬件的系统平台。它包含了Ruff SDK、Ruff OS。Rap Registry等。从技术上讲,Ruff 是一个 JavaScript 运行时,专为硬件开发而设计。

Ruff 对硬件进行了抽象,使用了基于事件驱动、异步 I/O 的模型,使硬件开发变得轻量而且高效。硬件抽象层,使得操做硬件宛如普通程序库,减小了硬件领域进入门槛。

Ruff 为开发人员提供了无缺的开发服务。

从项目生产、软件包管理、应用管理、外设管理到固件管理等一系列现代软件开发方式。PC 端完毕开发,无需烧板子。提高开发人员的开发效率。

Ruff 还提供了无缺的測试框架,支持 assert、test、mock 等模块,在开发机上測试逻辑,硬件測试也能 TDD。

官网(ruff.io) 上给出的示比例如如下:

$.ready(function() {
   $('#led-0').turnOn();
});

打开电路板上的一个LED 灯,就是如此的简单。

眼下,一个 Ruff 硬件同一时候仅仅能运行一款 Ruff 应用,它将拥有本身独立的进程。着可能也受到JavaScript自身的限制吧。

关注性能

性能是全栈关注的一个重要维度。那句“过早优化是万恶之源”其实是咱们对高德纳先生的断章取义,原文是这种:

咱们应该在好比97%的时间里,忘掉小处的效率;
过早优化是万恶之源。


但咱们不该该错过关键的3%中的机会。

其实是非关键路径上的优化是万恶之源,问题在于怎样肯定咱们的代码是否在关键路径上。

不论节省的时间多么少,花费在关键路径上的性能优化都是值得的。

对于性能优化工具,用于JavaScript源码压缩有 google Closure complier。packer。YUI compressor,JSmin等。页面的性能优化工具备YSlow 和Page Speed等。

实际上。不论什么有意义且可靠的性能測试都是基于统计学上的合理实践。 就JavaScript 代码自己的性能而言,benchmarkjs 是一个很是好的工具,而jsperf.com 提供了对JavaScript 运行环境的性能測试。

总之,JavaScript 是一个具备强大生命力的语言,前端框架更是突飞猛进。从Angular。Vue。到React, 乃至React Native,给人以应接不暇的感受,但是,老码农认为基础认识仍是很是必要的,勿在浮沙筑高塔。

參考阅读

https://developer.mozilla.org/en-US/docs/Web/JavaScript 

https://tc39.github.io/ecma262/#sec-global-object


微信扫一扫关注该公众号

相关文章
相关标签/搜索