创建例外

如果像.promo的组件加到header,然后buttons又加到.promo
里面,使其看起来像一个正常按钮,而不是标题按钮。

如果你用子代选择器,那你将要给header
buttons写一大串样式,而且还不能影响promo
buttons,混乱,容易出错,而且容易失控的数量会增加:

CSS

/* Regular button styles. */ .Button { } /* Button styles that are
different when inside the header. */ .Header .Button { } /* Undo
button styles in the header that are also in promo. */ .Header .Promo
.Button { }

1
2
3
4
5
6
7
8
/* Regular button styles. */
.Button { }
 
/* Button styles that are different when inside the header. */
.Header .Button { }
 
/* Undo button styles in the header that are also in promo. */
.Header .Promo .Button { }

使用自定义属性,你可以简单的更新任何你想要的新按钮属性,或重置他们回默认样式,无视这些例外,改变的方式总是相同的。

CSS

.Promo { –Button-backgroundColor: initial; –Button-borderColor:
initial; –Button-color: initial; }

1
2
3
4
5
.Promo {
  –Button-backgroundColor: initial;
  –Button-borderColor: initial;
  –Button-color: initial;
}

1.不要写不需要的样式

例如:在任何地方写 display:block
时都需要注意。因为许多元素默认都有这种样式。

再比如,定义继承了你定义过字体大小的元素的字体大小。

这里的目标是双重的:

  • 减少 CSS 文件的长度,这样更容易在 CSS 文件中定位代码位置。
  • 明确 CSS 类实际需要做什么,而不是定义一堆已有的垃圾样式。

一个常见问题是有许多不再使用的 CSS 样式没有清理掉,为了简洁起见,这些
CSS 样式可以完全删除。

JavaScript 在浏览器中是怎么跑起来的?

对于现在的计算机来说,它们只能读懂“机器语言”,而人类的大脑能力有限,直接编写机器语言难度有点大,为了能让人更方便地编写程序,人类发明了大量的“高级编程语言”,JavaScript
就属于其中特殊的一种。

为什么说是特殊的一种呢?由于计算机并不认识“高级编程语言”写出来的东西,所以大部分“高级编程语言”在写好以后都需要经过一个叫做“编译”的过程,将“高级编程语言”翻译成“机器语言”,然后交给计算机来运行。但是,JavaScript
不一样,它没有“编译”的过程,那么机器是怎么认识这种语言的呢?

实际上,JavaScript
与其他一部分脚本语言采用的是一种“边解释边运行”的姿势来运行的,将代码一点一点地翻译给计算机。

那么,JavaScript
的“解释”与其他语言的“编译”有什么区别呢?不都是翻译成“机器语言”吗?简单来讲,“编译”类似于“全文翻译”,就是代码编写好后,一次性将所有代码全部编译成“机器语言”,然后直接交给计算机;而“解释”则类似于“实时翻译”,代码写好后不会翻译,运行到哪,翻译到哪。

“解释”和“编译”两种方法各有利弊。使用“解释”的方法,程序编写好后就可以直接运行了,而使用“编译”的方法,则需要先花费一段时间等待整个代码编译完成后才可以执行。这样一看似乎是“解释”的方法更快,但是如果一段代码要执行多次,使用“解释”的方法,程序每次运行时都需要重新“解释”一遍,而“编译”的方法则不需要了。这样一看,“编译”的整体效率似乎更高,因为它永远只翻译一次,而“解释”是运行一次翻译一次。并且,“编译”由于是一开始就对整个代码进行的,所以可以对代码进行针对性的优化。

JavaScript
是使用“解释”的方案来运行的,这就造成了它的效率低下,因为代码每运行一次都要翻译一次,如果一个函数被循环调用了
10 次、100 次,这个执行效率可想而知。

好在聪明的人类发明了
JIT(Just-in-time)技术,它综合了“解释”与“编译”的优点,它的原理实际上就是在“解释”运行的同时进行跟踪,如果某一段代码执行了多次,就会对这一段代码进行编译优化,这样,如果后续再运行到这一段代码,则不用再解释了。

JIT 似乎是一个好东西,但是,对于 JavaScript
这种动态数据类型的语言来说,要实现一个完美的 JIT 非常难。为什么呢?因为
JavaScript
中的很多东西都是在运行的时候才能确定的。比如我写了一行代码:const sum = (a, b, c) => a + b + c;,这是一个使用
ES6 语法编写的 JavaScript
箭头函数,可以直接放在浏览器的控制台下运行,这将声明一个叫做 sum
的函数。然后我们可以直接调用它,比如:console.log(sum(1, 2, 3)),任何一个合格的前端开发人员都能很快得口算出答案,这将输出一个数字
6。但是,如果我们这样调用呢:console.log(sum('1', 2, 3)),第一个参数变成了一个字符串,这在
JavaScript
中是完全允许的,但是这时得到的结果就完全不同了,这会导致一个字符串和两个数字进行连接,得到
"123"。这样一来,针对这一个函数的优化就变得非常困难了。

虽说 JavaScript 自身的“特性”为 JIT 的实现带来了一些困难,但是不得不说
JIT 还是为 JavaScript 带来了非常可观的性能提升。

预处理器变量的限制

在继续写之前,我想强调的是,我真的很喜欢CSS
预处理器,我的所有项目都在使用它。预处理器做了一件非常了不起的事情,即时你知道他最终出来的就是原始的CSS,任然可以感受这个神器的时代。

任何工具,都有他的局限性,有一个炫酷的外观会让人惊喜而忽略了其中的限制,特别是新用户。

7. 有时候需要重新发明轮子,但请认真考量其他可行选项

在客户端项目中构建自己的网格 CSS 框架,这就是一个重复造轮子的例子。

据我的经验,除非你想知道它是如何工作的,否则自己写这些东西并没有多大的好处。出现过很多自己构建的边缘案例,而且也没有理由不去用别人已经做得很好且免费的东西。

也就是说,自己造一个轮子可能是一个很好的学习经验 –
但这在应用生产中或许并不适用。

好吧,但 JavaScript 插件呢?

在谈论 JavaScript 或 jQuery
插件时,我会说,对于那些与你使用的任何组件都很好集成的常见组件来说,情况也是如此。
这里有一些例子,例如: JavaScript 转盘之间交换照片,或日期选择器。

这里的边缘案例可以使用一些带有封装组件逻辑(React,Ember,Angular等)的
JavaScript 框架插件。
如果你想要做的事情相对简单,有时可能比将这些插件放到这些组件中更麻烦。

例如,如果我使用的是依赖于 jQuery 的项目,但是会在 React
中构建我自己的模块,那么我将使用基础模块或引导模块(仅仅是因为编写组件以便通过引入
jQuery 插入到 React 组件中)。

.wasm 文件 与 .wat 文件

WebAssembly 是通过 *.wasm
文件进行存储的,这是编译好的二进制文件,它的体积非常的小。

在浏览器中,提供了一个全局的 window.WebAssembly 对象,可以用于实例化
WASM 模块。

图片 1

WebAssembly
是一种“虚拟机器语言”,所以它也有对应的“汇编语言”版本,也就是 *.wat
文件,这是 WebAssembly
模块的文本表示方法,采用“S-表达式(S-Expressions)”进行描述,可以直接通过工具将
*.wat 文件编译为 *.wasm 文件。熟悉
LISP
的同学可能对这种表达式语法比较熟悉。

预处理器变量不能级联(层叠)

每当你使用变量,作用域的范围不可避免,这个变量应该全局吗?应该是file/module?还是块作用域?

CSS 最终是为HTML的样式,事实证明还有另外一种有用的方法是变量的范围:DOM
元素,但是preprocessors不能运行在浏览器且从未看见标记

参考一个网站,试图给` 的元素添加一个 classuser-setting-large-text他们更倾向于更大的文本大小 。
一旦这个class设置,更大
$font-size`变量赋值就会运用:

CSS

$font-size: 1em; .user-setting-large-text { $font-size: 1.5em; } body {
font-size: $font-size; }

1
2
3
4
5
6
7
8
9
  $font-size: 1em;
 
.user-setting-large-text {
  $font-size: 1.5em;
}
 
body {
  font-size: $font-size;
}

但是,就像上面媒体查询例子,Sass 直接忽略变量赋值,
意味着这种事是不可能的。他输出的:

CSS

body { font-size: 1em; }

1
2
3
  body {
  font-size: 1em;
}

5. 利用 BEM 来防止过多的嵌套

BEM (Block Element
Modifier)
策略可以地真正防止过度嵌套。

使用 BEM
的一个例子是当你使用一个具有很多具体样式的组件时,它会变得很复杂很混乱并且无法使用
utilitiy 。

举个上述那样的例子:

JavaScript

// HTML snippet <div class=”profile”> <img src=”person.jpg”
class=”profile__photo”/> </div> // BEM CSS .profile {
background-color: white; border: 1px solid #ccc; } .profile__photo {
border-radius: 50%; border: 1px solid #000; }

1
2
3
4
5
6
7
8
9
10
11
12
13
// HTML snippet
<div class=”profile”>
  <img src=”person.jpg” class=”profile__photo”/>
</div>
// BEM CSS
.profile {
  background-color: white;
  border: 1px solid #ccc;
}
.profile__photo {
  border-radius: 50%;
  border: 1px solid #000;
}

从这个例子中你可以看出,我定义的样式表中 .profile__photo 是与 .profile
嵌套的,但是没有使用嵌套的类。这就是 BEM
最厉害的地方,这也是为什么我推荐使用 BEM 。

小结

WebAssembly 的出现,使得前端不再只能使用 JavaScript
进行开发了,C、C++、Go 等等都可以为浏览器前端贡献代码。

这里我使用 wat
文件来编写的两个例子仅供参考,实际上在生产环境不大可能直接使用 wat
来进行开发,而是会使用 C、C++、Go 等语言编写模块,然后发布为
WebAssembly。

WebAssembly 的出现不是要取代 JavaScript,而是与 JavaScript
相辅相成,为前端开发带来一种新的选择。将计算密集型的部分交给 WebAssembly
来处理,让浏览器发挥出最大的性能!

1 赞 收藏
评论

图片 2

媒体查询的响应式特性

很多网站在项目布局使用“gap”和“gutter
定义默认间距和填充页面各个部分,很多时候,你想要这个“gutter”的值根据浏览器窗口的大小而不同。在大屏幕上你想要每一项之间有足够的空间,但小屏幕又负担不起那么大的空间,所以“gutter”的值要较小。

正如我上面提到的,在媒体查询里面Sass
不能正常运行,所以你必须每个单独处理。

下面的例子定义了变量$gutterSm,
$gutterMd$gutterLg,然后给每个变量申明一个单独的规则:

CSS

/* Declares three gutter values, one for each breakpoint */ $gutterSm:
1em; $gutterMd: 2em; $gutterLg: 3em; /* Base styles for small screens,
using $gutterSm. */ .Container { margin: 0 auto; max-width: 60em;
padding: $gutterSm; } .Grid { display: flex; margin: -$gutterSm 0 0
-$gutterSm; } .Grid-cell { flex: 1; padding: $gutterSm 0 0 $gutterSm; }
/* Override styles for medium screens, using $gutterMd. */ @media
(min-width: 30em) { .Container { padding: $gutterMd; } .Grid { margin:
-$gutterMd 0 0 -$gutterMd; } .Grid-cell { padding: $gutterMd 0 0
$gutterMd; } } /* Override styles for large screens, using $gutterLg.
*/ @media (min-width: 48em) { .Container { padding: $gutterLg; } .Grid
{ margin: -$gutterLg 0 0 -$gutterLg; } .Grid-cell { padding: $gutterLg 0
0 $gutterLg; } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/* Declares three gutter values, one for each breakpoint */
 
$gutterSm: 1em;
$gutterMd: 2em;
$gutterLg: 3em;
 
/* Base styles for small screens, using $gutterSm. */
 
.Container {
  margin: 0 auto;
  max-width: 60em;
  padding: $gutterSm;
}
.Grid {
  display: flex;
  margin: -$gutterSm 0 0 -$gutterSm;
}
.Grid-cell {
  flex: 1;
  padding: $gutterSm 0 0 $gutterSm;
}
 
/* Override styles for medium screens, using $gutterMd. */
 
@media (min-width: 30em) {
  .Container {
    padding: $gutterMd;
  }
  .Grid {
    margin: -$gutterMd 0 0 -$gutterMd;
  }
  .Grid-cell {
    padding: $gutterMd 0 0 $gutterMd;
  }
}
 
/* Override styles for large screens, using $gutterLg. */
 
@media (min-width: 48em) {
  .Container {
    padding: $gutterLg;
  }
  .Grid {
    margin: -$gutterLg 0 0 -$gutterLg;
  }
  .Grid-cell {
    padding: $gutterLg 0 0 $gutterLg;
  }
}

使用自定义属性来完成相同的东西,你只需要定义样式即可。你可以使用一个
gutter 属性,然后随着媒体查询的变化,更新gutter
的值,它就会做出相应的变化。

CSS

:root { –gutter: 1.5em; } @media (min-width: 30em) { :root { –gutter:
2em; } } @media (min-width: 48em) { :root { –gutter: 3em; } } /* *
Styles only need to be defined once because * the custom property
values automatically update. */ .Container { margin: 0 auto; max-width:
60em; padding: var(–gutter); } .Grid { –gutterNegative: calc(-1 *
var(–gutter)); display: flex; margin-left: var(–gutterNegative);
margin-top: var(–gutterNegative); } .Grid-cell { flex: 1; margin-left:
var(–gutter); margin-top: var(–gutter); }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
:root { –gutter: 1.5em; }
 
@media (min-width: 30em) {
  :root { –gutter: 2em; }
}
@media (min-width: 48em) {
  :root { –gutter: 3em; }
}
 
/*
* Styles only need to be defined once because
* the custom property values automatically update.
*/
 
.Container {
  margin: 0 auto;
  max-width: 60em;
  padding: var(–gutter);
}
.Grid {
  –gutterNegative: calc(-1 * var(–gutter));
  display: flex;
  margin-left: var(–gutterNegative);
  margin-top: var(–gutterNegative);
}
.Grid-cell {
  flex: 1;
  margin-left: var(–gutter);
  margin-top: var(–gutter);
}

虽然有额外增加的自定义属性语法,但是相比冗长的代码完成同样的事明显好很多。这里只考虑了三个变量,如果变量越多,这将节省更多的代码。

下面的演示使用的是上面的代码自动构建的一个基本的网站布局,gutter的值跟随窗口的变化而变化,浏览器的支持自定义属性的话,效果屌屌的!
图片 3
View the demo on CodePen: editor
view / full
page

3. 在 CSS 中定义工具以使你的 CSS 更实用

我们将 ‘工具’ 定义为这样一种 CSS
类,它是为某种特定的目标而生,而不是为了表示一整个元素。

在流程的 CSS 框架,比如 Bootstrap 和 Foundation
中,你会经常看到对这一策略的应用。

在流程框架中可以看到这样一些例子:

.hide { display: none; } .text-center { text-align: center; }

1
2
.hide { display: none; }
.text-center { text-align: center; }

比如,使用 .hide
之后,就不需要每次都写一个类来隐藏页面上的元素,你可以直接在元素上使用
.hide 类,它会赋于元素 display: none; 样式。

我们已经创建了自己的工具文件并在各个应用之间共用,我们使用一些公共工具来减少为每个元素写特定样式的需求。

关于这点,有一个不错的例子,使用 margin 和 padding 工具。这里我们有一个
padding 工具的示例(我们也定义了 margin 相关的工具,以及只有
padding-left 和 padding-right 的工具等):

.padding-0 { padding: 0; } .padding-xxs { padding: 5px; } .padding-xs {
padding: 10px; } .padding-sm { padding: 20px; } .padding-md { padding:
30px; } .padding-lg { padding: 40px; } .padding-xl { padding: 50px; }
.padding-xxl { padding: 60px; }

1
2
3
4
5
6
7
8
.padding-0 { padding: 0; }
.padding-xxs { padding: 5px; }
.padding-xs { padding: 10px; }
.padding-sm { padding: 20px; }
.padding-md { padding: 30px; }
.padding-lg { padding: 40px; }
.padding-xl { padding: 50px; }
.padding-xxl { padding: 60px; }

通过组合这些工具,我们可以保持空白像素一致,同时快速为页面做上标记,还不用写大量的
CSS。

在定义工具的时候,你应该考虑到会多次使用它们。如果是一次性的样式,或者只是想组合一些常用的样式,那么最好是定义成专门的
CSS 类。

一个非常简单的例子

我们来看一个非常简单的例子,这个已经在 Chrome 69 Canary 和 Chrome 70
Canary 中测试通过,理论上可以在所有已经支持 WebAssembly
的浏览器中运行。(在后文中有浏览器的支持情况)

首先,我们先使用 S-表达式 编写一个十分简单的程序:

;; test.wat (module (import “env” “mem” (memory 1)) ;; 这里指定了从
env.mem 中导入一个内存对象 (func (export “get”) (result i32) ;;
定义并导出一个叫做“get”的函数,这个函数拥有一个 int32
类型的返回值,没有参数 memory.size)) ;; 最终返回 memory
对象的“尺寸”(单位为“页”,目前规定 1 页 = 64 KiB = 65536 Bytes)

1
2
3
4
5
;; test.wat
(module
  (import "env" "mem" (memory 1)) ;; 这里指定了从 env.mem 中导入一个内存对象
  (func (export "get") (result i32)  ;; 定义并导出一个叫做“get”的函数,这个函数拥有一个 int32 类型的返回值,没有参数
    memory.size))  ;; 最终返回 memory 对象的“尺寸”(单位为“页”,目前规定 1 页 = 64 KiB = 65536 Bytes)

可以使用 wabt 中的
wasm2wat
工具将 wasm 文件转为使用“S-表达式”进行描述的 wat 文件。同时也可以使用
wat2wasm
工具将 wat 转为 wasm。

在 wat 文件中,双分号 ;; 开头的内容都是注释。

上面这个 wat 文件定义了一个
module,并导入了一个内存对象,然后导出了一个叫做“get”的函数,这个函数返回当前内存的“尺寸”。

在 WebAssembly
中,线性内存可以在内部直接定义然后导出,也可以从外面导入,但是最多只能拥有一个内存。这个内存的大小并不是固定的,只需要给一个初始大小
initial,后期还可以根据需要调用 grow
函数进行扩展,也可以指定最大大小
maximum(这里所有内存大小的单位都是“页”,目前规定的是 1 页 = 64 KiB
= 65536 Bytes。)

上面这个 wat 文件使用
wat2wasm
编译为 wasm 后生成的文件体积非常小,只有 50 Bytes:

$ wat2wasm test.wat $ xxd test.wasm 00000000: 0061 736d 0100 0000 0105
0160 0001 7f02 .asm…….`…. 00000010: 0c01 0365 6e76 036d 656d 0200
0103 0201 …env.mem…… 00000020: 0007 0701 0367 6574 0000 0a06 0104
003f …..get…….? 00000030: 000b ..

1
2
3
4
5
6
$ wat2wasm test.wat
$ xxd test.wasm
00000000: 0061 736d 0100 0000 0105 0160 0001 7f02  .asm…….`….
00000010: 0c01 0365 6e76 036d 656d 0200 0103 0201  …env.mem……
00000020: 0007 0701 0367 6574 0000 0a06 0104 003f  …..get…….?
00000030: 000b                                     ..

为了让这个程序能在浏览器中运行,我们还必须使用 JavaScript
编写一段“胶水代码(glue code)”,以便这个程序能被加载到浏览器中并执行:

// main.js const file = await fetch(‘./test.wasm’); const memory = new
window.WebAssembly.Memory({ initial: 1 }); const mod = await
window.WebAssembly.instantiateStreaming(file, { env: { mem: memory, },
}); let result; result = mod.instance.exports.get(); // 调用 WebAssembly
模块导出的 get 函数 console.log(result); // 1 memory.grow(2); result =
mod.instance.exports.get(); // 调用 WebAssembly 模块导出的 get 函数
console.log(result); // 3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// main.js
 
const file = await fetch(‘./test.wasm’);
const memory = new window.WebAssembly.Memory({ initial: 1 });
const mod = await window.WebAssembly.instantiateStreaming(file, {
  env: {
    mem: memory,
  },
});
let result;
result = mod.instance.exports.get();  // 调用 WebAssembly 模块导出的 get 函数
console.log(result);  // 1
memory.grow(2);
result = mod.instance.exports.get();  // 调用 WebAssembly 模块导出的 get 函数
console.log(result);  // 3
 

这里我使用了现代浏览器都已经支持的 ES6 语法,首先,使用浏览器原生提供的
fetch 函数加载我们编译好的 test.wasm 文件。注意,这里根据规范,HTTP
响应的 Content-Type 中指定的 MIME 类型必须为 application/wasm

接下来,我们 new 了一个 WebAssembly.Memory
对象,通过这个对象,可以实现 JavaScript 与 WebAssembly 之间互通数据。

再接下来,我们使用了 WebAssembly.instantiateStreaming 来实例化加载的
WebAssembly 模块,这里第一个参数是一个 Readable Stream,第二个参数是
importObject,用于指定导入 WebAssembly 的结构。因为上面的 wat
代码中指定了要从 env.mem 导入一个内存对象,所以这里就得要将我们 new
出来的内存对象放到 env.mem 中。

WebAssembly 还提供了一个 instantiate
函数,这个函数的第一个参数可以提供一个
ArrayBuffer
或是
TypedArray。但是这个函数是不推荐使用的,具体原因做过流量代理转发的同学可能会比较清楚,这里就不具体解释了。

最后,我们就可以调用 WebAssembly 导出的函数 get 了,首先输出的内容为
memoryinitial 的值。然后我们调用了 memory.grow 方法来增长
memory 的尺寸,最后输出的内容就是增长后内存的大小 1 + 2 = 3

为什么我为css变量如此兴奋

2016/01/01 · CSS ·
变量

原文出处: Philip
Walton   译文出处:腾讯ISUX   

几个星期前,CSS Variables ——CSS 变量草案发布在了W3C官方
,更准确的应该叫CSS
自定义属性,目前在Chrome
Canary
版里面已经支持,开启该功能见附[1]

当Chrome浏览器工程师Addy
Osmani第一时间把这消息发布在twitter后,遭到了数万人的否定、敌视和怀疑。于我而言,更多的感到是一个惊喜,因为这个功能实在让人太兴奋了。

快速的扫了一遍之后,发现99%人抱怨的无外乎这两点:

  • 语法太丑和不够简洁
  • Sass 、Less早就有这些玩意了,不太care

虽然我承认我也对这语法很反感,更重要的是理解语法不只是反复无常的在选择。CSS工作组讨论很久语法的长度,他们提取了一些点,考虑到CSS的语法兼容不会与未来增加的其他语言冲突。

CSS
预处理器是一个非常出色的工具,但是它们的变量是静态的,有语法作用域。Native
CSS
变量,从另一面来看,它们是一个完全不同类型的变量:因为它们是动态的,他们的作用域是DOM,事实上,这也是困惑该不该称他们为变量,它们实际上是CSS
属性,这也给了他们一个机会,来解决这个功能完全不同的问题。

在这篇文章中,我将讨论一些CSS 自定义属性这个功能,而且不用CSS
预处理器来做。当然我还演示一些新的设计模式,自定义功能的启用。文章最后讨论一下,我认为在未来最有可能的是预处理变量和自定义变量一起使用,两个东西取长补短,珠联璧合。

注意:这篇文章不是介绍CSS
自定义属性,如果你还从来没听说过他们,不熟悉他们是如何工作的,可以看看这里

8. 在乎你的前端代码

最后,我建议你做的最重要的事情是在乎你写的前端代码,掌握代码,并且始终不断地改进代码(同时也要不断提升自己!)。

在一个需要长期维护的应用程序和一个很难上手且总是出问题的项目之间,我相信不断改进代码是最大重要因素之一。

写 CSS
时使用这八个技巧,你不仅可以节省你自己的时间,还能节省未来接手你代码的开发者的时间。

你采取哪一个建议来精简你的 CSS 代码?请在下方评论,让我知道你的选择。

1 赞 3 收藏
评论

图片 2

WebAssembly 的现状与未来

目前 WebAssembly
的二进制格式版本已经确定,未来的改进也都将以兼容的形式进行更新,这表示
WebAssembly 已经进入现代标准了。

图片 5

现在的 WebAssembly 还并不完美,虽说已经有使用 WebAssembly 开发的 Web
游戏出现了,但是还有很多不完美的地方。

比如,现在的 WebAssembly 还必须配合“JavaScript glue
code”来使用,也就是必须使用 JavaScript 来 fetch WebAssembly
的文件,然后调用
window.WebAssembly.instantiatewindow.WebAssembly.instantiateStreaming
等函数进行实例化。部分情况下还需要 JavaScript
来管理堆栈。官方推荐的编译工具 Emscripten
虽然使用了各种黑科技来缩小编译后生成的代码的数量,但是最终生成的
JavaScript Glue Code 文件还是至少有 15K。

未来,WebAssembly 将可能直接通过 HTML
标签进行引用,比如:<script src="./wa.wasm"></script>;或者可以通过
JavaScript ES6 模块的方式引用,比如:import xxx from './wa.wasm';

线程的支持,异常处理,垃圾收集,尾调用优化等,都已经加入 WebAssembly
的计划列表中了。

发表评论

电子邮件地址不会被公开。 必填项已用*标注