Giter Club home page Giter Club logo

blog's People

Contributors

ninesean avatar

Watchers

 avatar

blog's Issues

[工具]win10下「CapsLock」与左「Ctrl」互换

win10下「CapsLock」与左「Ctrl」互换

  • 由于频繁用到ctrl键,而ctrl在键盘上的位置实在尴尬,故而如果对调「CapsLock」与左「Ctrl」,那就顺手多了,效率up。

  • macOS可以直接在图形界面配置几个功能键的键位映射。

  • 而win下只能通过第三方程序或者在注册表设置,以下步骤通过设置注册表实现win10下「CapsLock」与左「Ctrl」互换。

  1. win+r

  2. 键入regedit

  3. 点击进入以下目录
    image

  4. 在目录下新建名为「Scancode Map」的二进制值(通过鼠标右键->New->Binary Value)文件 。
    image

  5. 打开该文件键入值如下
    image

  6. 重启系统生效。

参考

[笔记]前端工程师的入门与进阶(justjavac)

前端工程师的入门与进阶(justjavac)笔记

  • 少用变量,多用常量

  • 循环不提倡使用for、while,提倡使用函数式map、reduce、every、some

  • 现在如今,根据业务分前后端

    • 处理业务逻辑、提供API、提供接口则为后端
    • 如果处理的是展示逻辑(不管是在浏览器端还是服务器端生成的页面)则为前端
  • 定目标、学技能

  • 没有高工资的语言,只有高工资的开发者

  • jjc方法:一人分饰多角写项目

  • 要解锁更多的技能树

  • 加入技术型公司

  • 设计模式

    • 应用在什么场景
    • 解决了什么问题
    • 为什么能解决这种问题
    • 怎么才能解决问题
  • 如何读框架源码

    • 从第一个正式的发布版开始读
    • 比较不同版本的更改
  • 新手害怕改变,高手迎接改变,大神以不变应万变

  • 把爱好当成自己的孩子——为他付出

  • jQuery

    • 优点:兼容性
    • 缺点:频繁操作DOM
  • 定位

    • 工程路线:写业务代码
    • 底层路线:封装组件、库,性能调优
  • 切忌一项技能重复使用5年

  • 做多10个项目不如做精一个项目

  • react

    • 单向数据流
    • 函数式编程
      • 把界面定义成状态+属性,再通过函数映射为一个展示层
    • 包特别大
    • 为了兼容老的语法,版本有很多稀奇古怪
    • 为了兼容浏览器,强制有个合成时间
    • 状态异步
  • vue

    • 轻量
    • 门槛低
    • 个人开发但成功案例不少
  • rxjs

    • 用于处理数据比较多的页面
  • vue.js使用flow做标注

  • JS前沿网站

    • JS news
    • echo JS

[翻译]网购需要缴税么?

[翻译]网购需要缴税么?

消费者网购衣服食物甚至到汽车,是否要缴纳购置税成了世界性的问题。有的人把互联网当做主要销售平台--因为免税。事实上,许多线上零售商以此来吸引顾客。然而,有一些案例确是要收税的。

买方所在地

一般来讲,如果线上零售商在维护一个实体店,而其中大多数商品都要缴销售税,那么线上卖给本地客户则要缴税。但是,如果卖给外地顾客,则不用收税。

举个例子,假如有个Pete,在加利福尼亚生活工作,喜欢在网上购买他餐馆所用的食用油、香料。他通常在一家总部和仓库都在内华达的网店下单。因为Pete的网购的卖家是在加利福利亚之外,那这家企业与Pete的交易是不用交税的。

大型网站的线上销售如何避税?

大型网站通过建立专门负责线上交易的子公司来避税。

举个例子,你线上购物的网店和你所在当地对应线下实体店的法人可能不一样。因为特定的线上网店在你所在地没有实体店,就不用缴税了。所以争议就非常大了,未来可能会有相关立法以保障那些没有线上网店的实体店无法享受到免税部分。

然而,线上零售商允许消费者在实体店退货而法律上讲他们是独立法人,这使问题变得更加复杂。消费者线上免税购物,但是又能在实体店退货。

消费者可能要求报告和纳税

由于消费者线上免税消费,但是住在美国又要缴税,他们被要求报告他们的消费并且直接向州税务机构缴纳销售税。当消费者被要求这样做了,就是所谓的使用税。

销售税和使用税唯一的区别就是个人最后是否给钱给州政府。销售税——只有零售商缴税,而使用税——消费者直接缴税。然而,收取小额消费税收的成本往往比免税更大。所以,国家税务机关尝试把焦点更多的放在收取那些线上免税大额消费的使用税上,比如汽车与船艇。

意识到这些,许多的州已经加强了使用税法的实行并且正在尝试让本地居民缴纳应交税费。

以下广告就不翻译了...

end...(本来想了解在国内网购外国商品的税收问题,通篇翻译完才发现原来是美国国内的网购税收...orz)

[翻译] 信仰(Faith与Belief)的差别

[翻译] 信仰(Faith与Belief)的差别

如果你问大多数人,他们会说faith与belief是同样的东西。我以前亦是如此,这造成了各种困惑。

问题是它们之间相互关联,这让彼此的意思非常接近。太过接近以至于许多现代圣经的翻译对两者不作区分,而这导致了更多的困惑。

当我们把faith与belief等同对待,这使得耶稣看起来有点自相矛盾。举个例子,下面给出New Living Translation翻译的马太福音第17章第20节(圣经的某个章节):

“You don’t have enough faith,” Jesus told them. “I tell you the truth, if you had faith even as small as a mustard seed, you could say to this mountain, ‘Move from here to there,’ and it would move. Nothing would be impossible.”

— Matthew 17:20 (NLT)

读到这,似乎是耶稣告诉他的信徒他们的问题是没有足够的信仰。我的意思是"you don't have enough faith"还能有其它含义么?

但是他接着解释说我们根本不需要任何信仰,就能看到奇迹发生,不是吗?

这没有什么意义。如果耶稣说只需要一点信仰那为何他又承认他们根本不需要任何信仰?

多小的信仰是足够的?似乎我们需要一种衡量信仰有多小的方法。

不知道你是怎么想的,但是我觉得这没啥意义。

现在让我们看看New King James Version是如何翻译同样的章节的:

So Jesus said to them, “Because of your unbelief; for assuredly, I say to you, if you have faith as a mustard seed, you will say to this mountain, ‘Move from here to there,’ and it will move; and nothing will be impossible for you.

— Matthew 17:20 (NKJV)

这篇翻译更少矛盾了。耶稣告诉信徒哪怕你的信仰再微不足道,也能够解决问题。

现在我们可以着手做些什么了。我们的目的就是指出belief与faith究竟是什么,然后在生活中应用好。

Belief是什么

为了解释两者不同,让我们从belief开始。它的含义到底是什么呢?

如果你想的话可以在字典中查到belief。它的定义是:

Belief – An opinion or judgement in which a person is fully persuaded.

可见belief是我们彻底坚信的东西。通常却非总是的情况下它们是我们通过获取信息与经验总结而成的。因此,belief会随着时间的积累--我们获取了更多的知识,历经生活的磨练而改变。

Faith有何不同?

我们再一次翻开字典然后找到faith的定义。

对我而言,更容易理解它的方式是:

Faith = ( Belief + Action + Confidence )

Faith包含了belief却又不仅于此。Faith还要有行动。如果它没有推动我们采取真正的行动去推进某事,就根本不是真正的faith。詹姆斯曾经说过:

So you see, faith by itself isn’t enough. Unless it produces good deeds, it is dead and useless.

— James 2:17

直到我们行动,不然它只是一堆文字。詹姆斯说除非"faith"产生行动,不然实际上它是死的,或者不能称之为"faith"。

再者,有些人会变得困惑并且转变观念然后尝试去做些好的事情生成信仰。然而詹姆斯从没说过好的事情能产生信仰。他说过我们的信仰,如果它是真的,那么会促使我们自发地去做好的事情。

有点跑题了。

信仰等式最后的组成部分是信心。

Confidence – Trust that is based on knowledge or past experience

基本的信心能衡量我们对信仰有多坚定。

把它融合在一起

所以现在能看出belief与faith是多么紧密相连。它们的差异是微妙的。但是如果理解了就会使得耶稣如上面马太福音第17章第20节中所述的事情变得更有意义。

当我们相信有足够的信心就能促进行动时,我们锻炼了信仰。并且不用太多信仰就能产生很大变化,甚至发生不可思议的事情。

当然你能看到没有信仰,不相信事情会成真,相信谎言,完全抑制了信仰的作用。没有信仰让我们不再相信生活中的奇迹。

我们花了太多的时间和精力尝试增强信仰 。我们祈祷、恳求上帝,祈求他能给我们更多信仰。

建立信仰比你想象中容易

我们的问题是确实没有信仰,而非缺乏信仰。

好消息使我们变得有信仰。按部就班就能达成,这是相当简单的。我们只需要被真理说服取代固执于误解和谎言。

我们的**向真理解放的越多,就越能信服真理。

解放**最佳的方式就是学习圣经。我们花越多的时间探索圣经的真理,就越能够被真理折服。

我们越被真理折服,就变得更有信心。

时间不会太长的,在我们带着信仰去行动而发现做事时的差别。

你想要更有信仰么?花更多的时间在圣经的阅读、学习和思考上。这会潜移默化的影响你的信仰,让它成长!

这很简单,不是么?

[翻译]Promise

Promise


想象你是一个顶级歌手,你的粉丝每天都向你催促新的单曲。

为了安抚粉丝,你承诺一旦发行就会寄给他们。你给了张列表给粉丝。他们填上地址以便新歌发布所有订阅可以立即得到。并且如果发生状况以至无法发布,粉丝也能得到通知。

皆大欢喜:对于你来说不用再被催逼了;对于粉丝来说不会错过单曲。

类比真实生活事件,我们在编程中:

1."产品代码"执行需要时间。比如,加载一个远程脚本。这就对应的"单曲"。
2.当准备好时"消费代码"要得到结果。许多功能要得到结果,这就对应"粉丝"。
3.promise是一个特殊的JavaScript对象把它们连接到一起。这就对应"列表"。产品代码创造promise并把它给到它们以便订阅结果。

promise对象构造语法如下:

let promise = new Promise(function(resolve, reject) {
  // executor (the producing code, "singer")
});

传给new Promise的回调叫做执行者。当promise创建时,它会自动调用。它包括了"产品代码",最终将作为结果完成的。在上面类比的几个词中,执行者就是"单曲"。

得到的promise对象有几个内置属性:

  • state——初始状态是"pending",然后变为"fulfilled"或者"rejected"。
  • result——一个随意的值,初始为undefined

当执行者执行完毕,他会调用其中一个:

  • resolve(value) - 表明任务成功完成:
    • state切换为"fulfilled"。
    • result变为value
  • reject(error) - 表明发生错误:
    • state切换为rejected
    • resulterror

举个例子,把上面的内容串起来:

let promise = new Promise(function(resolve, reject) {
  // the function is executed automatically when the promise is constructed

  alert(resolve); // function () { [native code] }
  alert(reject);  // function () { [native code] }

  // after 1 second signal that the job is done with the result "done!"
  setTimeout(() => resolve("done!"), 1000);
});

运行上面的代码我们能看到2件事情:

1.执行者通过new Promise自动并且立即调用。
2.执行者接受2个参数:resolvereject-这2个函数来自Javascript引擎。不用自建,而执行者在准备就绪时要调用它们。

经过1秒钟,执行者调用resolve("done")产生以下结果:

这是成功的例子。

下面是一个执行者报错拒绝promise的例子:

let promise = new Promise(function(resolve, reject) {
  // after 1 second signal that the job is finished with an error
  setTimeout(() => reject(new Error("Whoops!")), 1000);
});

小结:执行者通常要花时间执行任务,然后调用resolve或者reject来改变响应promise对象的状态(state)。

promise处于resolved或者rejected称为"settled",相反的是"pending"状态。

  • 只能是返回结果或者报错

执行者只能调用resolve或者rejectpromise状态变更后就是最终状态了。

resolvereject之后的调用将被忽略:

let promise = new Promise(function(resolve, reject) {
  resolve("done");

  reject(new Error("…")); // ignored
  setTimeout(() => resolve("…")); // ignored
});

执行者任务的完成只能有一个结果或者报错。在编程中,存在其它的数据结构允许许多"动态"的结果,例如流和队列。对比promises它们各有优劣。它们没被Javascript核心原生支持,并且缺乏某些promises提供的语言特征,让我们把焦点放回到promises上。

假如我们调用resolve/reject时传入更多参数-只有第一个有效,更多的参数将被忽略。

  • 使用Error对象reject

技术上来讲在调用reject是能像resolve一样传入任何类型的参数。但是推荐使用Error对象reject(或者是继承自Error对象)。原因下文将提及。

  • 立即调用resolve/reject

实际上执行者通常异步处理事情并且之后常会调用resolve/reject,但是却不必要。可以立即调用resolve或者reject,如下:

let promise = new Promise(function(resolve, reject) {
  resolve(123); // immediately give the result: 123
});

例如,当我们开始执行任务时就已经发生,然后看到所有的事情都已经完成。技术上来说这很好:我们立即就有了一个resolved promises

  • stateresult是内置的

promises对象的stateresult属性是内置的。在我们的代码中虽然不能直接访问它们,但却可以使用.then/catch方法访问,详见下文。

"消费者":".then"与".catch"

promise对象提供了"产品代码"(执行者)与"消费功能"(想接受result/error)之间的连接。"消费功能"可以通过使用promise.thenpromise.catch方法注册。

.then语法如下:

promise.then(
  function(result) { /* handle a successful result */ },
  function(error) { /* handle an error */ }
);

第一个函数的参数在promises resolved后得到结果后运行,第二个则是在rejected获取错误后运行。

举例如下:

let promise = new Promise(function(resolve, reject) {
  setTimeout(() => resolve("done!"), 1000);
});

// resolve runs the first function in .then
promise.then(
  result => alert(result), // shows "done!" after 1 second
  error => alert(error) // doesn't run
);

rejection的例子:

let promise = new Promise(function(resolve, reject) {
  setTimeout(() => reject(new Error("Whoops!")), 1000);
});

// reject runs the second function in .then
promise.then(
  result => alert(result), // doesn't run
  error => alert(error) // shows "Error: Whoops!" after 1 second
);

如果我们只对成功完成感兴趣,那就提供只提供一个参数给.then

let promise = new Promise(resolve => {
  setTimeout(() => resolve("done!"), 1000);
});

promise.then(alert); // shows "done!" after 1 second

如果我们只对错误感兴趣,那么我们就用.then(null,function)或者使用别名为.catch(function)的方法:

let promise = new Promise((resolve, reject) => {
  setTimeout(() => reject(new Error("Whoops!")), 1000);
});

// .catch(f) is the same as promise.then(null, f)
promise.catch(alert); // shows "Error: Whoops!" after 1 second

.catch(f)的作用类似`.then(null,f),不过只是一个变形。

  • 确定的promises then方法会立即执行

如果promise在pending,.then/catch程序直到获取结果才处理。否则,如果 promise已经确定,将会立即执行:

// an immediately resolved promise
let promise = new Promise(resolve => resolve("done!"));

promise.then(alert); // done! (shows up right now)

这便利了工作——有时需要时间,有时要立即完成。这保证了不同的需求。

  • .then/catch的处理总是异步的

更准确来说,当.then/catch程序被执行时,首先进入内部的队列。Javascript引擎从队列获取程序,在当前代码完成后执行,类似于setTimeout(...,0)

换句话说,当.then(hander)将被触发,代替setTimeout(handler,0)做些事情。

在下面的例子中promise立即resolved,所以.then(alert)马上触发:alert函数进入队列并且在代码完成后立即执行。

// an immediately resolved promise
let promise = new Promise(resolve => resolve("done!"));

promise.then(alert); // done! (right after the current code finishes)

alert("code finished"); // this alert shows first

所以在.then后面的代码总是先执行(尽管在预完成的promises例子中)。通常这不重要,只是在某些场景中这会有问题。

下面让我们看看更多关于promises处理异步的实例。

实例:loadScript

我们已经在上个章节获得了loadScript函数(用来加载脚本的)。

下面是基于回调的变形,让我们回想一下:

function loadScript(src, callback) {
  let script = document.createElement('script');
  script.src = src;

  script.onload = () => callback(null, script);
  script.onerror = () => callback(new Error(`Script load error ` + src));

  document.head.append(script);
}

promises重构。

新的loadScript函数不用回调。代替的是创建并返回一个promise对象用于加载完成的处理。外面可以通过.then调用:

function loadScript(src) {
  return new Promise(function(resolve, reject) {
    let script = document.createElement('script');
    script.src = src;

    script.onload = () => resolve(script);
    script.onerror = () => reject(new Error("Script load error: " + src));

    document.head.append(script);
  });
}

用法:

let promise = loadScript("https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.2.0/lodash.js");

promise.then(
  script => alert(`${script.src} is loaded!`),
  error => alert(`Error: ${error.message}`)
);

promise.then(script => alert('One more handler to do something else!'));

我们能立即看出基于回调语法的好处:

  • Callbacks

    • 必须准备好callback当我们调用loadScript时。换句话说,在loadScript调用前必须知道该做什么的结果。
    • 只能有一个回调。
  • Promises

    • promises能让我们以很自然的顺序去用代码写东西。首先我们执行loadScript,然后.then写入在获得结果后要做的事情。
    • 我们可以使用promise调用.then任意次并且在之后的任意时间只要我们想。

所以promises已经让我们的代码更流畅和更灵活。但是还有更多美妙之处,在下一章节让我们拭目以待。

任务

再次resolve promise

let promise = new Promise(function(resolve, reject) {
  resolve(1);

  setTimeout(() => resolve(2), 1000);
});

promise.then(alert);
  • 答案
输出:1。
第二次调用`resolve`会被忽略,因为只考虑第一次的`reject/resolve`,之后将被忽略。

使用promise延迟

内建函数setTimeout使用回调。造个promise替代。

函数delay(ms)需要返回一个promisepromise将在ms毫秒后resolve以便我们使用.then。如下:

function delay(ms) {
  // your code
}

delay(3000).then(() => alert('runs after 3 seconds'));
  • 答案
function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

delay(3000).then(() => alert('runs after 3 seconds'));

请注意此任务`resolve`未传参调用。`delay`后我们不用返回任何值,只是确认延迟。

promise画圈圈...

重构上一章的任务中showCircle函数,以便返回一个promise代替接受一个回调。

新的用法:

showCircle(150, 150, 100).then(div => {
  div.classList.add('message-ball');
  div.append("Hello, world!");
});

基于上一章的任务的解决方案

[翻译]回调介绍

回调介绍


Javascript中许多动作都是异步的。

举个例子,来看看loadScript(src):

function loadScript(src) {
  let script = document.createElement('script');
  script.src = src;
  document.head.append(script);
}

这个函数的目的是加载一个新的script。当在document中插入了<script src="...">时,浏览器就会加载并且执行这个脚本。

应用如下:

// loads and executes the script
loadScript('/my/script.js');

函数是异步调用的,因为脚本的加载是在稍后完成的。

函数调用发起了脚本的加载,然后继续执行。当脚本在加载中,下面的代码可能已经执行完毕,如果加载要耗费些时间,其他的脚本可能也同时运行。

loadScript('/my/script.js');
// the code below doesn't wait for the script loading to finish

现在我们要用到这个新脚本,它可能包含生命新的函数,我们要用到这些函数。但是我们不能在loadScript(...)调用后立马使用这些函数:

loadScript('/my/script.js'); // the script has "function newFunction() {…}"

newFunction(); // no such function!

很自然的,浏览器可能没有时间加载脚本。至此,loadScript函数没有提供追踪加载完成的方法。脚本加载,最终运行,就这样。但是我们要知道什么时候可以使用脚本里的新函数和变量。

callback函数作为第二个参数传入loadScript中,当监本加载时就会执行这个回调:

function loadScript(src, callback) {
  let script = document.createElement('script');
  script.src = src;

  script.onload = () => callback(script);

  document.head.append(script);
}

如果我们要在脚本中调用一些新的函数,就要在回调中写入:

loadScript('/my/script.js', function() {
  // the callback runs after the script is loaded
  newFunction(); // so now it works
  ...
});

这个办法就是:第二个参数作为一个函数(通常是匿名函数),当动作完成以后再运行。

给出范例:

function loadScript(src, callback) {
  let script = document.createElement('script');
  script.src = src;
  script.onload = () => callback(script);
  document.head.append(script);
}

loadScript('https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.2.0/lodash.js', script => {
  alert(`Cool, the ${script.src} is loaded`);
  alert( _ ); // function declared in the loaded script
});

这就称为异步编程的"callback-based"风格。一个函数要异步的做些事情,那必须把它作为回调传入另外一个函数,在这个函数做完某些事情后再运行回调。

在这里我们用loadScrip演示,但回调是一个常用的方法。

回调中的回调

如何有序的加载2个脚本:先加载一个,接着再加载第二个?

显然可以通过把第二个loadScript在回调中调用,就像这样:

loadScript('/my/script.js', function(script) {

  alert(`Cool, the ${script.src} is loaded, let's load one more`);

  loadScript('/my/script2.js', function(script) {
    alert(`Cool, the second script is loaded`);
  });

});

在外面的loadScript完成后,回调触发里面的loadScript

那么再加一个脚本呢?

loadScript('/my/script.js', function(script) {

  loadScript('/my/script2.js', function(script) {

    loadScript('/my/script3.js', function(script) {
      // ...continue after all scripts are loaded
    });

  })

});

那么,每一个新的动作就要在里面加个回调。如果少的话那还好,但是太多的话就不太好了,所以让我们马上看看其它的变种。

错误处理

上面的例子我们没有考虑到报错。当脚本加载失败了呢?我们的回调应该对此响应。

下面对loadScript改善后一追踪加载错误:

function loadScript(src, callback) {
  let script = document.createElement('script');
  script.src = src;

  script.onload = () => callback(null, script);
  script.onerror = () => callback(new Error(`Script load error ` + src));

  document.head.append(script);
}

成功调用callback(null,script),反之调用callback(error)

用法:

loadScript('/my/script.js', function(error, script) {
  if (error) {
    // handle error
  } else {
    // script loaded successfully
  }
});

这种loadScript的用法也是非常常见。这叫做"error-first callback"风格。

约定如下:

1.回调的第一个参数是处理错误,然后callback(err)被调用。
2.第二个参数处理成功(如果需要继续再加参数),调用callback(null,result1,result2...)

厄运金字塔

开始的时候这是个可行的异步代码。它确实是。只有一两个调用时看了起来不错。

但是在多个异步动作,比如像下面一个接一个的嵌套:

loadScript('1.js', function(error, script) {

  if (error) {
    handleError(error);
  } else {
    // ...
    loadScript('2.js', function(error, script) {
      if (error) {
        handleError(error);
      } else {
        // ...
        loadScript('3.js', function(error, script) {
          if (error) {
            handleError(error);
          } else {
            // ...continue after all scripts are loaded (*)
          }
        });

      }
    })
  }
});

以上代码:
1.我们加载1.js,然后如果没有报错。
2.我们加载2.js,然后如果没有报错。
3.我们加载3.js,然后如果没有报错就做一些其他的事情(*)

作为嵌套调用,代码变得更深切增加了管理的难度,特别是如果我们有更多的代码代替上面例子中的...,可能是循环,条件等语句A。

这就是所谓的“回调地狱“或者叫做”厄运金字塔“。

callback-hell

随着嵌套回调,如上图"pyramid"在每次异步动作后往右生长,代码逐渐缠绕致使失控。

所以这种代码不好。

我们能够通过声明独立的函数处理每一步动作来缓和问题,如下:

loadScript('1.js', step1);

function step1(error, script) {
  if (error) {
    handleError(error);
  } else {
    // ...
    loadScript('2.js', step2);
  }
}

function step2(error, script) {
  if (error) {
    handleError(error);
  } else {
    // ...
    loadScript('3.js', step3);
  }
}

function step3(error, script) {
  if (error) {
    handleError(error);
  } else {
    // ...continue after all scripts are loaded (*)
  }
};

看到没?我们做到了,并且不再有深度嵌套了,这是因为我们为每一步动作声明了单独的顶级函数。

虽然实现了功能,但代码却看起来像是撕散割裂的部分。你可能注意到了它难于阅读。必须在2个区块来回切换来阅读理解。这非常的不方便,特别是阅读者不熟悉代码,不知道要哪些区块是功能相关可联系切换的。

另外为命名为step*的函数仅仅单纯地回避了”厄运金字塔“的问题。没有人会在这一系列的动作链之外重复使用它们。所以这会稍微扰乱命名空间。

我们想要更好的方式。

幸运的是有其他的方法避免”厄运金字塔”。其中一个最好的方式就是使用“promises”,详见下章。

任务

用回调动态生成圆

这个任务动态生成圆。

我们不仅需要一个圆,并且在里面显示消息。这个信息需要在动画完成后再显示,不然看起来很丑。

为了完成任务,定义一个`showCircle(cx,cy,radius)`函数画圆,但是没有监控它完成与否。

添加一个回调作为参数:showCircle(cx,cy,radius,callback),当动画完成后调用。这个callback要接受<div>作为参数。

举例如下:

showCircle(150, 150, 100, div => {
  div.classList.add('message-ball');
  div.append("Hello, world!");
});

Demo

[工具]命令行Tips

命令行Tips

解决端口被占用报错

image

//查询占用了8080端口的进程PID
netstat -ano|findstr "8080"

//通过PID(比如查询PID为2348)杀死进程
tskill 2348

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

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

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.