clearives / clearives.github.io Goto Github PK
View Code? Open in Web Editor NEW个人博客
Home Page: https://clearives.cc
个人博客
Home Page: https://clearives.cc
this is the correct way to do this:
{
"linters": {
"eslint": {
"args": [
"--ignore-path", ".eslintignore",
],
}
}
}
this is the correct way to do this:
edit /Users/zengxianghui/Library/Application Support/Sublime Text 3/Packages/User/SublimeLinter.sublime-settings
"eslint": {
"@disable": true,
"args": [],
"excludes": [
"**/node_modules/**",
"**/build/*.js",
"**/config/*.js",
"**/server/**"
]
}
1、koa中加版本号
app.use(koaManifestRev({
manifest: path.join(__dirname, env === 'pro' ? 'build': '', 'rev-manifest.json'),
prepend: '/'
}));
注意这代码必须加在路由前,不然不生效
在我们React项目中,我们接受到BASE64的字符串,我们需要解密,我们想到的是第三方模块js-base64
/*"use strict";*/
const BASE64 = require('js-base64').Base64;
function formatStatus (status) {
var decoder = BASE64.decode(status);
var resultObj = JSON.parse(decoder);
return resultObj;
}
let result = formatStatus('e2E6MSxiOjJ9') // {a:1,b:2}
Buffer 实例一般用于表示编码字符的序列,比如 UTF-8 、 UCS2 、 Base64 、或十六进制编码的数据。 通过使用显式的字符编码,就可以在 Buffer 实例与普通的 JavaScript 字符串之间进行相互转换。
/*"use strict";*/
let obj = {a:1,b:2};
// 编码
let base64Str = new Buffer(obj).toString('base64');
// 解码
let result = new Buffer(base64Str, 'base64').toString(); // {a:1,b:2}
css3的动画 animation属性,如果动画里面需要动画的元素是transform,那么动画的这个元素及其子元素是不能运行点击事件,如果有a标签,也是不能跳转链接的。是transform属性改变了元素的层级,也就是z-index属性。
在兄弟节点上加一个隐藏的元素,所有属性一样,通过这个元素控制事件
When there are circular require() calls, a module might not have finished executing when it is returned.
当有循环的require调用时,模块返回时可能尚未完成它的执行
// a.js
console.log('a starting');
exports.done = false;
const b = require('./b.js');
console.log('in a, b.done = %j', b.done);
exports.done = true;
console.log('a done');
// b.js
console.log('b starting');
exports.done = false;
const a = require('./a.js');
console.log('in b, a.done = %j', a.done);
exports.done = true;
console.log('b done');
// main.js
console.log('main starting');
const a = require('./a.js');
const b = require('./b.js');
console.log('in main, a.done = %j, b.done = %j', a.done, b.done);
When main.js loads a.js, then a.js in turn loads b.js. At that point, b.js tries to load a.js. In order to prevent an infinite loop, an unfinished copy of the a.js exports object is returned to the b.js module. b.js then finishes loading, and its exports object is provided to the a.js module.
翻译:当 main.js 加载 a.js 时, a.js 又加载 b.js。 此时, b.js 会尝试去加载 a.js。 为了防止无限的循环,会返回一个 a.js 的 exports 对象的 未完成的副本 给 b.js 模块。 然后 b.js 完成加载,并将 exports 对象提供给 a.js 模块。
简单的说就算,为了防止模块载入的死循环,Node.js在模块第一次载入后会把它的结果进行缓存,下一次再对它进行载入的时候会直接从缓存中取出结果,所以在这种循环依赖情形下,不会有死循环。
执行node main.js :
虽然缓存解决了死循环的问题,但是大部分情况下我们不会这么写,而且这并没有解决正确导入模块的问题,所以,接下来看import,export📚。
react 宽度基于pt为单位, 可以通过Dimensions 来获取宽高,PixelRatio 获取密度。
基于flex的布局
3.图片布局
4.定位
5.文本元素
- 原文地址:https://medium.com/dailyjs/i-never-understood-javascript-closures-9663703368e8
- 原文作者:Olivier De Meulder
正如标题所述,JavaScript中的闭包对我来说一直很迷惑。我读过很多篇文章,工作中也使用过闭包,有时候我甚至不知道自己有用到闭包。
最近我参与了一个关于解释闭包的交流,最终点醒了我。下面我将采用这种方式在这篇文章中来解释闭包,让我赞扬Codesmith的优秀人才及他们的JavaScript The Hard Parts系列。
在你理解闭包之前,有一些概念很重要。其中之一是执行上下文(execution context)。
这篇文章是对执行上下文的一个很好的入门,下面引用它:
当代码在JavaScript中运行时,它的执行环境非常重要,执行环境为以下情况的一种:
全局代码 —— 代码首次载人执行的默认环境
函数代码 —— 每次代码执行进入函数体内
(…)
(…)让我们把执行上下文当做每次代码执行的环境/作用域
换句话说,每当我们启动程序,我们从全局执行上下文开始。一些变量在全局上下文下声明,我们称之为全局变量。当程序调用函数时,会发生什么呢?主要是以下几个步骤:
函数什么时候结束?当遇到return语句或遇到结束括号时}。当函数结束时,会发生以下情况:
在我们开始讲闭包前,让我们看一下下面这段代码。这看起来非常简单,任何读这篇文章的人都可能确切知道它的作用。
let a = 3;
function addTwo(x) {
let ret = x + 2;
return ret;
}
let b = addTwo(a);
console.log(b);
为了理解JavaScript引擎是如何工作的,下面让我们详细分析它。
对于一个非常简单的程序来说,这是一个非常冗长的解释,我们甚至还没有触及闭包。我相信会到达那里。但首先我们需要再绕一两次。
我们需要了解词法作用域的一些东西。我们来看一下下面的例子。
let val1 = 2;
function multiplyThis(n) {
let ret = n * val1;
return ret;
}
let multiplied = multiplyThis(6);
console.log("example of scope:", multiplied);
这里想表达的是我们在本地执行上下文中有变量,在全局执行上下文中有变量。 JavaScript的一个复杂之处在于它如何查找变量。如果它在本地执行上下文中找不到变量,它将在其调用上下文中查找它。如果没有在其调用上下文中找到它。反复地,直到它查看全局执行上下文。 (如果它没有找到它,它是undefined)。按照上面的例子,它将阐明它。如果您了解作用域的工作原理,则可以跳过此步骤。
这里我就不分析了,太长了,参考上面的就差不多知道了。
在这个例子中,我们只需要记住一个,函数可以访问在其调用上下文中定义的变量。这种情况我们称之为词法作用域。
第一个例子中函数返回的是一个数字,我们前面说过,函数可以返回任意值,下面让我们看个例子,函数返回函数,这对理解闭包很重要,下面例子我们开始分析:
let val = 7;
function createAdder() {
function addNumbers(a, b) {
let ret = a + b;
return ret;
}
return addNumbers;
}
let adder = createAdder();
let sum = adder(val, 8);
console.log("example of function returning a function: ", sum);
分析步骤为自己参照理解,不是直接翻译:
函数执行返回前,分析同第一个例子,来到return,createAdder上下文推出执行堆栈,变量addNumbers已经消失,但是函数addNumbers还存在,它被函数返回并且分配给变量adder了。下面就是在全局上下文下操作了,所以结果输出的是15。
翻译继续:
正如预期的那样,控制台将打印15。我想在这里说明几点。首先,函数定义可以存储在变量中,函数定义对程序是不可见的,直到被调用。其次,每次调用函数时,(临时)创建本地执行上下文。当函数完成时,执行上下文消失。函数在遇到return或者}括号时完成。
看看下一个代码,并试着弄清楚会发生什么。
function createCounter() {
let counter = 0;
const myFunction = function() {
counter = counter + 1;
return counter;
};
return myFunction;
}
const increment = createCounter();
const c1 = increment();
const c2 = increment();
const c3 = increment();
console.log("example increment", c1, c2, c3);
初步分析(非直译):
翻译继续:
不知道为何,increment函数记住了counter,它是怎么工作的呢?
是否counter存在于全局上下文中,console.log(counter),发现并没有,所以不是全局的,所以上面分析是错误的。
也许,当你调用increment时,它会以某种方式返回到它创建的函数(createCounter)?怎么会这样呢?变量increment包含函数定义,而不是它来自何处。所以那不是它。
所以必须有另一种机制。闭包。我们终于分析到了它。
下面是它的工作原理。每当声明一个新函数并将其赋值给变量时,都会存储函数定义以及闭包。闭包包含创建函数时范围内的所有变量。它类似于背包。功能定义附带一个小背包。在它的包中,它存储了创建函数定义时作用域内的所有变量。
再次分析(非直译):
所以现在我们了解这是如何工作的。要记住的关键是当声明一个函数时,它包含一个函数定义和一个闭包。闭包是函数创建时作用域内所有变量的集合。
您也许会问,任何函数是否都有闭包,甚至是在全局作用域内创建的函数?答案是对的。在全局作用域中创建的函数也会创建一个闭包。但由于这些函数是在全局作用域内创建的,因此它们可以访问全局作用域内的所有变量,所以闭包的概念并没有什么意义。
当函数返回一个函数时,就是让闭包的概念变得更加相关。返回的函数可以访问不在全局作用域内的变量,但它们仅存在于其闭包中。
我们要记住通过背包来打比方的方式形容闭包。当一个函数被创建并传递或从另一个函数返回时,它带有一个背包。并且在背包中是声明函数时作用域内的所有变量。
纯属个人翻译,经验不足,如有出入或问题欢迎指正,谢谢。
将 JS 基本数据类型、引用类型、普通对象、类实例、数组和映射,转换为可观察数据
用来修改 observable 的数据的动作,只有 action 和 runInAction 才能修改 observable
用来在异步的时候执行修改 observable 的数据的动作。例如网络请求后修改数据,这种模式的优势是它鼓励你不要到处写 action,而是在整个过程结束时尽可能多地对所有状态进行修改
根据现有的 observable 的值或其它计算值衍生出的值。只有在 view 使用了 computed 的值, computed 才会执行计算
我们通过定义一个count来监听,当所有的异步返回时,我们统一处理res。
let count = 0;
let res = {};
const done = function(key, val) {
res[key] = val;
count ++;
if(count === 3) {
render(res);
}
};
fs.readFile(template_path, 'utf8', (err, tp) => {
done('tp', tp);
});
db.query(sql, (err, data) => {
done('data', data);
});
$.get(demo.json, (err, res) => {
done('res', res);
});
var after = function(times, callback) {
var count = 0,res = {};
return function(key, val) {
res[key] = val;
count ++;
if(count == times) {
callback(res);
}
}
}
let promise1 = new Promise(function (resolve) {
resolve(1);
});
let promise2 = new Promise(function (resolve) {
resolve(2);
});
let promise3 = new Promise(function (resolve) {
resolve(3);
});
Promise.all([promise1, promise2, promise3]).then(function (res) {
console.log(res);
});
Promise.prototype.all = function (promises) {
let results = [];
let promiseCount = 0;
let promisesLength = promises.length;
return new Promise(function (resolve, reject) {
for (let val of promises) {
Promise.resolve(val).then(function (res) {
promiseCount++;
results[i] = res;
if (promiseCount === promisesLength) {
return resolve(results);
}
}, function (err) {
return reject(err);
});
}
});
};
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
checkscope()();
这端代码输出的答案是:local scope;为什么呢?
执行过程伪代码:
- [全局]EC
- [local scope]EC
- [f]EC
f函数执行能访问到local scope,所以输出local scope
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
checkscope()();
这端代码输出的答案是:local scope;为什么呢?
执行过程伪代码:
- [全局]EC
- [local scope]EC
- 闭包
执行到闭包时,[local scope]EC已出栈,所以闭包内this指向window,但是我们知道闭包能访问上层变量,也就是[local scope]EC里的变量,所以打印出来的也是local scope
注意,
这些情况下自动绑定 this 上下文到实例中,所以不能使用箭头函数。
(例如 plus: () => this.a++)。理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,this.a 将是 undefined。
安装Packages > Language Vue
打开插件代码可以配置默认vue模板
".text.html.vue":
"Vue Component":
"prefix": "template"
"body": """
<template>
$3
</template>
<script>
export default {
}
</script>
<style lang="${2:less}">
</style>
"""
新建vue文件,输入template,按下Tab键即可生成默认模板
constructor(props) {
super(props);
this.state = {
value: 0
};
this.handleClick2 = this.handleClick1.bind(this);
}
handleClick3 = () => {
console.log(this);
};
handleClick1() {
console.log(this);
}
<button onClick={this.handleClick1}>click 1</button>
<button onClick={this.handleClick2}>click 2</button>
<button onClick={this.handleClick3}>click 3</button>
Node模块允许你从被引入文件中选择要暴露给程序的函数和变量。如果模块返回的函数或变 量不止一个,那它可以通过设定exports对象的属性来指明它们。但如果模块只返回一个函数或变量,则可以设定module.exports属性。
// demo.js
console.log(module)
console.log(exports)
// 输出
Module {
id: '.',
exports: {},
parent: null,
filename:
'.../demo1.js',
loaded: false,
children: [],
paths:
[ ... ] }
{}
module.exports和exports一开始都是一个空对象{},本质上这两个指向的是同一块内存,
require引入的对象本质上是module.exports。这就产生了一个问题,当 module.exports和exports指向的不是同一块内存时,exports的内容就会失效。
最终在程序里导出的是module.exports。exports只是对module.exports的一个全 局引用,最初被定义为一个可以添加属性的空对象。如果把exports设定为别的,就打破了module.exports和exports之间的 引用关系。可是因为真正导出的是module.exports,那样exports就不能用了,因为 它不再指向module.exports了。如果你想维持那个链接,可以像下面这样让 module.exports再次引用exports。
// person.js
module.exports = {name: 'clearives'}
exports = {name: 'Mr、z'}
// demo.js
const person = require('./person')
console.log(person) // {name: 'clearives'}
module.exports = exports = {...};
参考:
Node.js实战
测试 号竟然一定要关注才能走微信授权
JS引擎中负责解释和执行JavaScript代码的线程只有一个,但是实际上还存在其他的线程。例如:处理AJAX请求的线程、处理DOM事件的线程、定时器线程、读写文件的线程(例如在Node.js中)等等,可以理解为任务队列
同步,也就是说按照顺序去做
console.log('node01')
console.log('node02')
// 输出:node01,node02
异步,也就是说不完全按照顺序去做
console.log('node01')
setTimeout(function () {
console.log('node02');
},100)
console.log('node03')
// 输出:node01,node03,node02
异步实现理解:
一个 JavaScript 运行时包含了一个待处理的消息队列。每一个消息都关联着一个用以处理这个消息的函数。在事件循环期间的某个时刻,运行时从最先进入队列的消息开始处理队列中的消息。为此,这个消息会被移出队列,并作为输入参数调用与之关联的函数。正如前面所提到的,调用一个函数总是会为其创造一个新的栈帧(函数调用形成了一个栈帧)。函数的处理会一直进行到执行栈再次为空为止;然后事件循环将会处理队列中的下一个消息(如果还有的话)。
主线程从"任务队列"中读取消息事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)
JS异步机制,遇到宏任务,先执行宏任务,宏任务执行结束,如果有可执行的微任务,执行微任务至结束,再开始新的宏任务,如果没有执行的微任务,直接开始新的宏任务。
原生小程序使用方法:
<button type="primary" open-type="getUserInfo" bindgetuserinfo="getUserInfo">
获取用户信息
</button>
<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">
获取手机号
</button>
Taro 使用方法:
<button
id="login-btn"
openType="getUserInfo"
lang="zh_CN"
onGetUserInfo="{this.getUserInfo}"
type="primary"
>
微信用户快速登录
</button>
<button openType="getPhoneNumber" onGetPhoneNumber="{this.getPhoneNumber}">
获取手机号
</button>
open-type 改为 openType,bindgetuserinfo 改为 onGetUserInfo,其它类似
Taro.checkSession({
success(res) {
console.log("success", res);
},
fail(res) {
console.log("fail", res);
}
})
.then(data => console.log(data))
.catch(() => {
console.log("wx.login");
});
getSetting 获取用户的当前设置。返回值中只会出现小程序已经向用户请求过的权限。
注意:getPhoneNumber 获取手机号权限不会出现在这里
在用户未授权过的情况下调用此接口,将不再出现授权弹窗,会直接进入 fail 回调(详见《公告》)。在用户已授权的情况下调用此接口,可成功获取用户信息。授权采用 button
当我们使用 picker-view 时会有一个 onChange 事件,也就是我们滚动了,我们能从 e.detail.value 中拿到联动的取值,当我们控制改变时,受控部分需要重制到自己的第一个,我们必须手动去修改值。
// 参考省市联动
cityChange(e) {
const pickerValue = e.detail.value
const { provinces, citys, value } = this.state
const provinceNum = pickerValue[0]
const cityNum = pickerValue[1]
const countyNum = pickerValue[2]
// 如果省份选择项和之前不一样,表示滑动了省份,此时市默认是省的第一组数据,
if (value[0] != provinceNum) {
const id = provinces[provinceNum].id
this.setState({
value: [provinceNum, 0, 0],
citys: address.citys[id],
areas: address.areas[address.citys[id][0].id]
})
} else if (value[1] != cityNum) {
// 滑动选择了第二项数据,即市,此时区显示省市对应的第一组数据
const id = citys[cityNum].id
console.log(id)
this.setState({
value: [provinceNum, cityNum, 0],
areas: address.areas[citys[cityNum].id]
})
} else {
// 滑动选择了区
this.setState({
value: [provinceNum, cityNum, countyNum]
})
}
}
参考:picker-view
交集
a.filter(function(v){ return b.indexOf(v) > -1 })
差集
a.filter(function(v){ return !(b.indexOf(v) > -1) }) .concat(b.filter(function(v){ return !(a.indexOf(v) > -1)}))
要在 node < 7.6 版本的 Koa 中使用 async 方法, 我们推荐使用 babel's require hook.
require('babel-register');
// 应用的其余 require 需要被放到 hook 后面
const app = require('./app');
要解析和编译 async 方法, 你至少应该有 transform-async-to-generator 或 transform-async-to-module-method 插件.
使用babel-plugin-add-module-exports
"plugins": [
"add-module-exports"
]
通过一系列功能直接传递控制,直到一个返回,Koa 调用“下游”,然后控制流回“上游”。
const Koa = require('koa');
const app = new Koa();
// logger
app.use(async (ctx, next) => {
console.log(1)
await next();
console.log(5)
const rt = ctx.response.get('X-Response-Time');
console.log(`${ctx.method} ${ctx.url} - ${rt}`);
});
// x-response-time
app.use(async (ctx, next) => {
console.log(2)
const start = Date.now();
await next();
const ms = Date.now() - start;
console.log(4)
ctx.set('X-Response-Time', `${ms}ms`);
});
// response
app.use(async ctx => {
console.log(3)
ctx.body = 'Hello World';
});
app.listen(3000);
上面例子打印的顺序是12345。
const http = require('http');
const Koa = require('koa');
const app = new Koa();
http.createServer(app.callback()).listen(3000);
export default async (ctx, next) => {
const start = new Date();
await next();
const ms = new Date() - start;
console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
}
这是一个logger中间件,app.use()用来加载中间件,每个中间件默认接受两个参数,第一个参数是 Context 对象,第二个参数是next函数。只要调用next函数,就可以把执行权转交给下一个中间件。
这里我们再回过头看上面的输出12345会引出中间件栈的说法,此处参考阮一峰老师的文章。
多个中间件会形成一个栈结构(middle stack),以"先进后出"(first-in-last-out)的顺序执行。
中间件包括同步和异步,异步的必须加上async await
如果代码运行过程中发生错误,我们需要把错误信息返回给用户。HTTP 协定约定这时要返回500状态码。Koa 提供了ctx.throw()方法,用来抛出错误,ctx.throw(500)就是抛出500错误。
const code2Token = async (ctx, next) => {
const request = ctx.request.body;
const code = request.code;
let res = await axios.get(`${wx.loginUrl}?appid=${wx.appId}&secret=${wx.appSecret}&js_code=${code}&grant_type=authorization_code`)
if (res.data.errcode && res.data.errcode !== 0) {
ctx.throw(412, res.data.errmsg) // 抛异常
}
let user = await WxUserService.getUserByOpenid(res.data.openid)
if (!user) {
user = await WxUserService.createUserByOpenid(res.data.openid)
}
let token = jwtUtil.sign({_id: user.openid})
ctx.body = Resp({
data: {
openid: user.openid,
token
}
})
};
该方法返回 path 的目录名
该方法使用平台特定的分隔符作为定界符将所有给定的 path 片段连接在一起,然后规范化生成的路径,零长度的 path 片段会被忽略。 如果连接的路径字符串是零长度的字符串,则返回 '.',表示当前工作目录。
该方法将路径或路径片段的序列解析为绝对路径。
http模块主要用于搭建HTTP服务。使用Node搭建HTTP服务器非常简单。
const http = require('http');
const PORT = 3001;
const server = http.createServer((req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write("Hello World");
res.end();
})
server.listen(PORT, function() {
console.log(`the server is started at port ${PORT}`)
})
const Emitter = require('events');
/** module.exports = class Application extends Emitter {...} 导出了koa类 **/
/** application.js 继承了 Emitter,所有它也包含了异步事件的处理能力,后面可以看到koa的错误处理会使用到Emitter提供的事件模型方法。 **/
常用的循环遍历方法有for循环,for..in,forEach,map等等...
for循环是最基本的遍历。
forEach() 方法对数组的每个元素执行一次提供的函数。
let arr = [1,2,3,4]
let _arr = arr.forEach((item) => {
console.log(item) // 1, 2, 3, 4
})
console.log(_arr) // undefined
map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果,不改变原数组。
let arr = [1,2,3,4]
let _arr = arr.map((item, i) => {
console.log(i) // 0, 1, 2, 3
return item + 1
})
console.log(_arr) // [ 2, 3, 4, 5 ]
filter、includes、find、findIndex这几个都是筛选数组的方法,下面一一分析
filter() 方法创建一个新数组,不改变原数组
let arr = [1,2,3,4]
let _arr = arr.filter((item, i) => {
return item > 2
})
console.log(_arr) // [3, 4]
includes() 方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回false。
find() 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined,不改变原数组,不创建新数组,只返回满足条件的第一个值。
let arr = [1,2,3,4]
let _arr = arr.find((item, i) => {
return item > 2
})
console.log(_arr) // 3
findIndex()方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回-1。
some() 方法测试是否至少有一个元素可以通过被提供的函数方法。该方法返回一个Boolean类型的值,不改变原数组。
every() 方法测试一个数组内的所有元素是否都能通过某个指定函数的测试。它返回一个布尔值。
若收到一个空数组,此方法在一切情况下都会返回 true。
Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for...in 循环遍历该对象时返回的顺序一致 。如果对象的键-值都不可枚举,那么将返回由键组成的数组。
let obj = {
a: 1,
b: 2
}
let _obj = Object.keys(obj)
console.log(_obj) // ["a", "b"]
for..in方法循环遍历对象自身的和继承的可枚举属性(不含Symbol属性)。
Object.getOwnPropertyNames()方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。
let obj = {
a: 1,
b: 2
}
let _obj = Object.keys(obj)
console.log(_obj) // ["a", "b"]
for(var i in obj) {
console.log(i,":",obj[i]); // a: 1, b: 2
}
let arr = [1, 3, 5]
console.log(Object.getOwnPropertyNames(obj)) // ["a", "b"]
console.log(Object.getOwnPropertyNames(arr)) // ["0", "1", "2", "length"]
break 语句中止当前循环,switch语句或label 语句,并把程序控制流转到紧接着被中止语句后面的语句。
continue 语句结束当前(或标签)的循环语句的本次迭代,并继续执行循环的下一次迭代
i = 0;
n = 0;
while (i < 5) {
i++;
if (i === 3) {
continue;
}
n += i;
}
与 break 语句的区别在于, continue 并不会终止循环的迭代,而是:
return语句终止函数的执行,并返回一个指定的值给函数调用者。
function counter() {
for (var count = 1; ; count++) { // 无限循环
console.log(count + "A"); // 执行5次
if (count === 5) {
return;
}
console.log(count + "B"); // 执行4次
}
console.log(count + "C"); // 永远不会执行
}
counter();
参考资料:
developer.mozilla.org
➜ アメージング😁 ~ npm install -g eslint
➜ アメージング😁 ~ eslint init //生成配置文件
下面是atom里面配置,安装Linter Eslint插件,
/usr/local/lib/node_modules //node_modules路径
~/.eslintrc //eslintrc path
这里要注意,如果你安装了nvm,node_modules路径配置可能不一样,或者使用nvm use system切换到默认node机制即可。
autoplayDisableOnInteraction: true //默认为false
centeredSlides: true //默认为false
测试标题
JS的继承方式有很多种,最理想的继承方式是寄生组合式继承。
function Person(name) {
this.name = name;
}
Person.prototype.sayHi = function() {
console.log(this.name + '-' + '-hi');
}
function SubPerson(name, age) {
Person.call(this, name);
this.age = age;
}
SubPerson.prototype = new Person();
SubPerson.prototype.constrcutor = SubPerson;
var sp = new SubPerson('clearives', 18);
console.log(sp);
sp.sayHi();
组合继承(构造函数和原型的组合)会调用两次父类构造函数的代码
function inheritPrototype(SubPerson, Person){
var protoType = Object.create(Person.prototype);
protoType.constructor = SubPerson;
SubPerson.prototype = protoType;
}
function Person(name) {
this.name = name;
}
Person.prototype.sayHi = function() {
console.log(this.name + '-' + '-hi')
}
function SubPerson(name, age) {
Person.call(this, name);
this.age = age;
}
inheritPrototype(SubPerson, Person);
var sp = new SubPerson('clearives', 18);
console.log(sp);
sp.sayHi();
这样避免了调用两次父类的构造函数,为其创建多余的属性。
function object(o) {
function F(){}
F.prototype = o;
return new F();
}
// 这个函数其实就是Object.create的简单实现
npm i koa-log4 --save
import path from 'path'
const logPath = path.resolve(__dirname, "../../logs/")
const config = {
appenders: {
access: {
type: 'dateFile',
pattern: '-yyyy-MM-dd.log',
filename: path.join(logPath, 'access.log'),
},
application: {
type: 'dateFile',
pattern: '-yyyy-MM-dd.log',
filename: path.join(logPath, 'application.log')
},
out: {
type: 'console',
},
},
categories: {
default: { appenders: [ 'out' ], level: 'info' },
access: { appenders: [ 'access' ], level: 'info' },
application: { appenders: [ 'application' ], level: 'WARN'}
}
}
export default config
// use
import config from './log4-conf'
log4js.configure(config)
const logger = log4js.getLogger()
const applicationLogger = log4js.getLogger('application')
const accessLogFunc = log4js.koaLogger(log4js.getLogger('access'))
logger表示常规的日志,在控制台输出,applicationLogger表示应用级别的日志,会输出在对应的log文件,accessLogFunc用app.use()加载,所有访问级别的日志会全部输出在对应的日志文件。
这里我们将方法统一挂载在global上,供其它地方使用。
import { logUtil } from '../utils/log4'
export default (ctx, next) => {
global.logUtil = logUtil
next()
}
日志级别主要分为以下几种
ctrl键组合
ctrl+a //光标移到行首
ctrl+b //光标左移
ctrl+f //光标右移
ctrl+c //杀死当前进程
ctrl+d //退格删除
ctrl+e //光标移到行尾
ctrl+h //删除光标前一个字符,同 delete 键相同
ctrl+k //清除光标后至行尾的内容
ctrl+l //清屏,相当于clear
ctrl+r //搜索之前打过的命令。会有一个提示
ctrl+u //清除光标前至行首间的所有内容
ctrl+w //移除光标前的一个单词
ctrl+t //交换光标位置前的两个字符
ctrl+y //粘贴或者恢复上次的删除
ctrl+d //删除光标所在字母;注意和backspace以及ctrl+h的区别,这2个是删除光标前的字符
ctrl+f //光标右移
ctrl+z //把当前进程转到后台运行,使用**fg**命令恢复。比如top -d1 然后ctrl+z ,到后台,然后fg,重新恢复
esc+d //删除光标后的一个词
esc+f //往右跳一个词
esc+b //往左跳一个词
esc+t //交换光标位置前的两个单词。
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.