JS类型转换奇技淫巧

很酷炫有木有!!!因为可读性低,所以有些技巧并不提倡使用。但遇见别人这样写,得看得懂是怎么一回事!

  • 转布尔型

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    !!''         //=> false
    !!null //=> false
    !!undefined //=> false
    !!NaN //=> false
    !!0 //=> false
    !!1 //=> true
    !!-1 //=> true
    !![] //=> true
    !!{} //=> true
    !!window //=> true
    !!Infinity //=> true
  • 转字符串

    1
    2
    '' + 123      //=> '123'
    '' + true //=> 'true'
  • 转数值型

    1
    2
    +new Date     //=> 1456480246437
    +'123' //=> 123
  • 向下取整

    1
    2
    3
    4
    ~~3.4          //=> 3
    3.4|0 //=> 3
    -3.4^0 //=> -3
    -3.4 >> 0 //=> -3
  • indexOf判断

    1
    2
    3
    4
    5
    6
    var arr = [1,2,3];
    if(!~arr.indexOf(4)){
    arr.push(4);
    }
    !!~arr.indexOf(1) //=> true
    !!~arr.indexOf(5) //=> false
  • 类数组转数组

    1
    2
    3
    var arrLike = {0:'abc',1:'xyz',length:2};
    Array.prototype.slice.call(arrLike) //=> ['abc','xyz']
    //常用 Array.prototype.slice.call(arguments)

hingsir.com首页的动画效果使用的是第三方动画库Animate.css,它包含了很多酷炫的动画效果(点击这里查看),基本的使用方法如下:

  • 引入css文件

    1
    2
    3
    <head>
    <link rel="stylesheet" href="animate.min.css">
    </head>
  • 给需要动画效果的元素添加对应的class

    1
    <div class="animated fadeIn">fadeIn</div>
  • 自定义动画的显示时机和持续时间

    1
    2
    3
    4
    5
    #yourElement {
    -vendor-animation-duration: 3s;
    -vendor-animation-delay: 2s;
    -vendor-animation-iteration-count: infinite;
    }

是不是非常简单!但是尽管进行了压缩,animate.min.css仍然有50kb那么大,那么有办法再进一步精简吗?就比如我只用到了bounce bounceInDown zoomIn,完全没必要引入所有动画效果。接下来将教你如何定制自己的动画库

  • 克隆animate.css库到本地

    1
    $ git clone https://github.com/daneden/animate.css.git
  • 安装npm依赖

    1
    $ npm install
  • 修改animate-config.json(建议先备份)
    将不需要的动画效果全删掉,最后留下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    {
    "attention_seekers": [
    "bounce"
    ],

    "bouncing_entrances": [
    "bounceInDown"
    ],

    "zooming_entrances": [
    "zoomIn"
    ]
    }

  • 生成animate.min.css

    1
    $ gulp

animate.min.css只剩下4kb,大功告成!

做项目的过程中遇到这样一个问题:提交表单到下一页,再点击浏览器后退按钮回到表单页,发现部分表单数据丢失或者还是旧的数据。检查响应头,确实设置了Cache-control:no-cache,但浏览器还是偷懒from cache了。百度,google了一圈发现解决方案都不尽如意,最后在SOF里输入几个英文关键字找到下面的问答完美解决。

Force reload/refresh when pressing the back button

仅仅设置Cache-control:no-cache并不够,还需设置Expires Last-Modified Pragma

PHP实现

1
2
3
4
5
6
7
8
// any valid date in the past
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
// always modified right now
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
// HTTP/1.1
header("Cache-Control: private, no-store, max-age=0, no-cache, must-revalidate, post-check=0, pre-check=0");
// HTTP/1.0
header("Pragma: no-cache");

其他语言可参照着进行相应的设置。

jstips 收录了,o(∩_∩)o

Fibonacci sequence is very familiar to everybody. we can write the following function in 20 seconds.

1
2
3
var fibonacci = function(n){
return n < 2 ? n : fibonacci(n-1) + fibonacci(n-2);
}

it works, but not efficient. it did lots of duplicate computing works, we can cache its previously computed results to speed it up.

1
2
3
4
5
6
7
8
9
10
11
var fibonacci = (function() {
var cache = [0, 1]; // cache the value at the n index
return function(n) {
if (cache[n] === undefined) {
for (var i = cache.length; i <= n; ++i) {
cache[i] = cache[i-1] + cache[i-2];
}
}
return cache[n];
}
})()

Also, we can define a higher-order function that accepts a function as its argument and returns a memoized version of the function.

1
2
3
4
5
6
7
8
var memoize = function(func){
var cache = {};
return function(){
var key = Array.prototype.slice.call(arguments).toString();
return key in cache ? cache[key] : (cache[key] = func.apply(this,arguments));
}
}
fibonacci = memoize(fibonacci);

And there is a ES6 version of the memoize function.

1
2
3
4
5
6
7
8
var memoize = function(func){
const cache = {};
return (...args) => {
const key = [...args].toString();
return key in cache ? cache[key] : (cache[key] = func(...args));
}
}
fibonacci = memoize(fibonacci);

we can use memoize() in many other situations

  • GCD(Greatest Common Divisor)
1
2
3
4
5
6
7
var gcd = memoize(function(a,b){
var t;
if (a < b) t=b, b=a, a=t;
while(b != 0) t=b, b = a%b, a=t;
return a;
})
gcd(27,183); //=> 3
  • Factorial calculation
1
2
3
4
var factorial = memoize(function(n) {
return (n <= 1) ? 1 : n * factorial(n-1);
})
factorial(5); //=> 120

检测jquery对象是否存在

2016-01-21 by @hingsir

检测$(selector)是否存在,相信不少人写过类似下面的代码:

1
2
3
4
5
if($(selector)){
// do something
}else{
//do other things
}

然而这样写是有问题的,因为$(selector返回的是一个object,即便未匹配到任何元素,也会返回空数组[]ToBoolean([])为true,那么else代码块永远也不会执行到,因此我们一般利用$(selector).length>0来检测。

关于this的指向问题,往往困扰着许多新人。this指的调用函数的那个对象,也即函数运行时所处的环境。函数有以下四种调用方式

  • 普通函数调用 this指向全局环境global,浏览器环境为window。严格模式下指向undefined
  • 对象方法调用 this指向该对象
  • 构造函数调用 this指向由构造函数实例化后的对象
  • apply/call调用 指定this指向,func.apply(obj),指向obj

往往记住这几条规律,就不大容易弄错this指向。但下面例子却往往令不少新人弄错

1
2
3
4
5
6
7
8
function A(){
this.prop = 'a';
function func(){
console.log(this.prop);
}
func();
}
new A();

上述代码执行结果会是什么呢?有不少面试者认为会打印出’a’,而实际上是undefined,为什么呢?

其实非常简单,这就是普通函数调用方式,this指向的就是全局对象,而全局对象并没有prop属性,结果当然为undefined。既然如此简单,为何那么多人弄错,这是因为func函数定义在A内,this.prop混淆视听,影响了他们的判断。

所以只要记住下面一句话,就不会搞错:

普通函数调用,不管该函数定义得多深,如果没显式指定其this指向,那么它就指向全局对象或者undefined

如果想调整上述例子使其打印出’a’,就可以利用func.apply(this)来实现。另外值得一提的是,A()和new A()的区别往往也会令人疏忽,有兴趣的可以看看A()执行结果。

2016年度计划

  • 完成手头上未读完的书籍
    《大秦帝国》《HTTP权威指南》《深入浅出NodeJs》
  • 再多读几本好书,计划每月一本
  • 巩固前端基础知识,深入学习es6/react,保持对新技术的关注。
  • 前端工程化实践
  • 生猴?随缘!