javascript 标签

console.time & console.timeEnd

为了比较具体代码快的运行速度我们需要一些度量工具。console.timeconsole.timeEnd是浏览器原生就支持的属性。具体用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function generate100Array() {
var arr = new Array(100);
for(var i = 0; i < 100; i++){
arr[i]='';
}
return arr
}
var a = generate100Array()
var b = generate100Array()
console.time('for')
for (var i = 0, len = a.length; i < len; i++) {
a[i] = i
}
console.timeEnd('for')
console.time('forEach')
b.forEach(function (el, index) {
b[index] = index
})
console.timeEnd('forEach')

你可以复制粘贴上面代码到chrome 终端运行一下,你会发现forforEach快,在我的chrome62.0 大概是快3-4倍。列出的理论,我都会提供相应代码,大家可以自己去试试。我只会在chrome下实验,并给出比较结果。

引子

开年的一次面试中记录下来的知识欠缺点,发现这块的东西自己也只是零零散散的,不够系统。面试真的是查漏补缺的好地方,所以就买了一波性能相关的书籍,慢慢看,慢慢总结吧。这一波是记录一些纯js相关的性能提升,不涉及具体框架,纯纯的在写js中需要注意的性能优化点。这部分相关的笔记,大部分内容来自阅读《高性能JavaScript》。

JS 的加载和执行

基本上这是一个常识,js的加载和执行会阻塞页面的渲染和交互。很多浏览器甚至是用单一进程来处理的UI刷新和JS执行。所以我们在让页面加载的过程中需要注意避免让js的加载执行和浏览器的UI渲染冲突。下面就是一些解决方案:

脚本位置

浏览器在处理html的时候,是从上到下解析的。所以,在HTML上的标签位置决定了浏览器解析的先后顺序。为了解决JS与浏览器冲突,通常情况下,我们是将JS放在最后的:

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 其他的html -->
<script src="http://hiluluke.cn/js/simple_build.js"></script> <!-- 将script放在最后,body前 -->
</body>
</html>

严格模式限制

By hiluluke on

js严格模式限制

  • 变量必须声明后再使用
  • 函数的参数不能有同名属性,否则报错
  • 不能使用with语句
  • 不能对只读属性赋值,否则报错
  • 不能使用前缀0表示八进制数,否则报错
  • 不能删除不可删除的属性,否则报错

$.extend

  • 用途
    扩展对象属性。
    第一个参数如果是true就递归的将source给target。

    1
    2
    $.extend(target, [source, [source2, ...]])  ⇒ target
    $.extend(true, target, [source, ...]) ⇒ target v1.0+
  • 相关代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    function extend(target, source, deep) {
    for (key in source)
    if (deep && (isPlainObject(source[key]) || isArray(source[key]))) {
    if (isPlainObject(source[key]) && !isPlainObject(target[key]))
    target[key] = {}
    if (isArray(source[key]) && !isArray(target[key]))
    target[key] = []
    extend(target[key], source[key], deep)
    }
    else if (source[key] !== undefined) target[key] = source[key]
    }

    // Copy all but undefined properties from one or more
    // objects to the `target` object.
    $.extend = function(target){
    var deep, args = slice.call(arguments, 1)
    if (typeof target == 'boolean') {
    deep = target
    target = args.shift()
    }
    args.forEach(function(arg){ extend(target, arg, deep) })
    return target
    }

今年重新找工作的时候面试官问了个问题,jQuery的链式函数调用的原理。当时一脸懵逼,因为完全没有去了解过。(事实证明面试能够很好的提高自己)

然后感觉直接去看jq的源码,要仔细看好感觉得花很长时间,还是先看看zepto,反正组织代码的原理都差不多。

构造

在立即调用函数中声明了3个东东:

1
2
3
4
5
6
7
8
9
10
zepto = {};
function Z(dom, selector) {
var i, len = dom ? dom.length : 0
for (i = 0; i < len; i++) this[i] = dom[i]
this.length = len
this.selector = selector || ''
}
$ = function(selector, context){
return zepto.init(selector, context)
}

当然声明的位置各有不同,Z函数很显然是构造函数,zepto是构造中间的一些方法的保留吧,然后$上挂上所有对外的方法。构造调用的基本流程是,$调用zepto的init,然后init函数做一些处理,再返回一个Z的`return zepto.Z(dom, selector)`,其中zepto.Z返回的就是一个构造函数Z。这样做的处理是要在$上吧zepto挂上,可以在插件里面改写。