underscore源码解析之类型判断函数

 首先将内置对象的原型链以及内置对象原型中的常用方法缓存在局部变量中

1
2
3
4
5
6
7
8
// 内置对象原型链
var ArrayProto = Array.prototype,
ObjProto = Object.prototype,
FuncProto = Function.prototype;
// 内置对象原型中的常用方法 e.g: toString
var toString = ObjProto.toString,
hasOwnProperty = ObjProto.hasOwnProperty;

 这样做的好处除了简洁代码之外,还有两个好处,首先是利于代码的压缩。而原生的对象原型无法进行压缩,e.g: Object.Protype压缩之后宿主就不认识了,但是objProto可以压缩为a,之后的调用也可以正常进行;然后是可减少在原型链中的查找次数(提高代码效率)。


 再定义一组javascript原生支持的判断函数,若宿主环境(浏览器/nodejs)支持,则直接返回。

1
2
3
4
var nativeIsArray = Array.isArray,
nativeKeys = Object.keys,
nativeBind = FuncProto.bind,
nativeCreate = Object.create;

 若不支持以上函数(es5之后才支持),则返回underscore自己写的判断函数。


  • 是否为DOM
1
2
3
4
5
_.isElement = function(obj) {
// 首先确保不是 null/undefined 等假值(!!obj),
// DOM 的 nodeType 为1,!!用于强制类型转换为 Boolean 值
return !!(obj && obj.nodeType === 1);
};
  • 是否为数组Array
1
2
3
4
_.isArray = nativeIsArray || function(obj) {
// call 方法可以使得任意 obj 都可以调用 toString 方法,即使是没有 toString 方法的对象
return toString.call(obj) === '[object aray]'
};
  • 是否为对象Object
1
2
3
4
5
6
_.isObject = function(obj) {
var type = typeof(obj);
// 除了普通对象之外,函数也是对象
// !!obj 是为了排除 null 的情况,因为 typeof null 也为 object
return type === 'function' || type === 'object' && !!obj;
};
  • 是否为布尔值Boolean
1
2
3
4
5
_.isBoolean = function(obj) {
// 除了 true 与 false 之外,布尔值还可能是 new Boolean() 哦
// 不过似乎直接用最后一种判断就可以了?
return obj === 'true' || obj === 'false' || toString.call(obj) === '[object boolean]';
};
  • 是否为arguments
1
2
3
4
5
6
7
8
if (!_.isArguments(arguments)) {
_.isArguments = function(obj) {
// 通过是否有 callee 方法判断
// 因为IE < 9 下对 arguments 调用 Object.prototype.toString.call 方法
// 返回的是 [object Object] ,而非 [object Arguments]
return _.has(obj, 'callee');
};
}
  • 是否为NaN
1
2
3
4
5
6
_.isNaN = function(obj) {
// NaN是一个Number类型,但是它不等于它本身
// ‘+’ 放在变量前面一般作用是把后面的变量变成一个数,
// 在这里已经判断为一个数仍加上 ‘+’,是为了把 var num = new Number() 这种没有值的数字也归为 NaN
return _.isNumber(obj) && obj !== +obj;
};
  • 是否为undefined
1
2
3
4
5
6
_.isUndefined = function(obj) {
// 一般我们都用 if(obj) 来直接判断undefined
// undefined 只是全局对象的一个属性,在局部环境能被重新定义
// 但是 void 0 始终是 undefined
return obj === void 0;
}
  • 是否有has指定key
1
2
3
4
_.has = function(obj, key) {
// obj 不能为 null 或者 undefined
return obj != null && hasOwnProperty.call(obj, key);
};

参考自:http://www.kancloud.cn/digest/underscore-source/82316

node.js同步获取request请求内容

 nodejs的异步执行给我们的编程带来了数不尽的好处,以至于我已经习惯了异步编程,某一次在执行request请求想要将其返回的body内容体传到request函数外时,发现怎么也获取不了,由于对node理解的不够深入透彻,我首先怀疑的竟然是会不会request不支持返回操作 or 难道操作仅在函数作用域内有效,后来才搞明白是异步执行惹的事儿,取值那会儿其实还没赋值呢。现在想想自己还是too naive..

 搞明白了是异步的问题之后,便想着如何把异步执行变同步执行,实现的方法有很多,我用的是Promise来实现。具体例子如下:

 简单地请求一下github并输出状态码 = =

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
"use strict"
let request = require('request');
let test = 'I am test';
// async
request({
url: 'https://github.com',
method: 'get'
}, (err, res, body) => {
if (res && res.statusCode === 200) {
test = res.statusCode + 'ok!';
console.log('inside request: ' + test);
} else {
test = 'error - -';
}
});
console.log('outside request: ' + test);

 执行结果如下:

1
2
3
$ node request.js
outside request: I am test
inside request: 200 ok!

 其实单从结果就可以看到,outside的执行是先于inside的,但是懵逼的我当时并没有发现,oops..

 言归正传,用上了Promise之后的画风是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
"use strict"
let test = 'I am test';
let request = require('request');
// sync
new Promise((resolve, reject) => {
request({
url: 'https://github.com',
method: 'get'
}, (err, res, body) => {
if (res && res.statusCode === 200) {
resolve(res.statusCode + ' ok!');
} else {
reject(' error - -');
}
});
}).then(result => {
test = result;
console.log("outside request: " + test);
}).catch(err => {
console.log("error: " + err)
})

 执行结果:

1
2
$ node request.js
outside request: 200 ok!

 这样一来,就能实现在request外也获取其内容的功能啦~~只要把代码都丢到then里面就可以了。

 好吧,写完之后发现,这他喵的这么简单我怎么会折腾这么久! T T

 最后的最后,想告诫自己

前端路阻且长,且行且珍惜。

英语学习计划--单词/文章/听力

关于英语学习计划,其实就简单地分单词、文章、听力三部分,下面的计划虽然乍一看量不多,但是我的最低要求就是,每一个单词、每一篇文章、每一集剧你都要做到真正理解,而不是一知半解。

1. 单词

  • 单词可以分为7个星期来学习,每星期学的单词递减(因为背单词是有惰性的,越到后面越不想背)
    • 第一个星期,每天学习35个新单词,第n天复习前n-1天的旧单词
    • 第二个星期,每天学习30个新单词,第n天复习前n-1天的旧单词
    • 第七个星期,每天学习5个新单词,第n天复习前n-1天的旧单词
  • 背单词软件就随意选择就好啦,像你之前用的扇贝都是可以的,设置好单词数就好,这样算下来,如果天天都坚持的话,能背下980个单词,建议前面和后面选择四级词汇,中间几个星期可以尝试下六级词汇。虽然不算多,但是能都记住就很了不起了。
  • little tip: 背单词的时候,一开始精力比较足可以看多一些拓展词汇(很多背单词软件都会有),但是建议越到后面越别看那么多,因为光是旧单词就可能会让你扛不下来了,我们要的是主单词一定掌握!短语什么的知道一两个足矣。

2. 文章

  • 阅读量可以不用太大,个人感觉3天一篇就够了,可以找一些阅读理解的文章去看,或者很多网站都有bbc中英文新闻可以看的。
  • 有个办法是自己一直也很想实践的,就是在看技术全英文档!既能提高英文水平,又能提高技术,何乐而不为呢?而且老外的东西很多都是比较新、总结得比较透彻比较可信的,国内也有很多牛人会去翻译国外技术大牛的博客,你可以找找。

3. 听力

听力还是离不开看美剧和听歌

  • 美剧的话我觉得看《绝望的主妇》就可以了,语速很慢,讲故事类型的,不像情景喜剧那样太容易让人忘记是为了学习,每一集结束后的那几句总结的话都是精髓!!
    • 可以每2天或者4天看一集,看的时候要求很高!第一遍不看字幕看完,试试能不能理解,然后看有字幕的第二遍。
    • 我自己是不喜欢看太多遍的,所以建议看的时候要用心,第二次不懂的地方可以停下来理解清楚再继续看。对于觉得比较有意思的句子还可以做笔记记录下来。
    • 印象中我前面几季都看完了,你看了也可以找我讨论,剧情也行,我当时看的时候是完全停不下来!
    • 可以找电影天堂这类型的网站下载,也可以直接安装个优酷app看或者在线看,但是优酷只有中文字幕,你自己下载的话可以下载到中英文字幕。给个地址你可以去下载:绝望的主妇第一季中英双字幕
  • 英文歌呢,推荐用网易云音乐听游戏歌曲啊摇滚歌曲啊,都是有中文翻译的,你平时学习java的时候也可以一边听歌,很神奇的事就是一开始你可能是喜欢这个节奏,但是突然某句歌词觉得听得懂,就会停下来看是什么意思,然后也许整首歌都知道什么意思了,还能学到新单词。
    • 推荐几首比较热的: bangbang、roar、falshlight、try everything等等,还有最近很喜欢的I want my tears back,你还可以找它们这些歌曲相关的歌单听更多同类型的歌!

最后咧,我觉得最重要的就是,既然你让我帮忙制定的这个计划,那你就要接受我的这些安排,不要有抵触心理,先去试试才知道能不能成功。如果过程中实在发现有什么是你做不到或者是有问题的我们再改改。

么么哒,加油亲爱的。