髙小浪

坑爹的排序

Chrome的bug?

在JavaScript里排序,我们一般都会用Array类的sort方法,例如:

1
2
3
// 将数组降序排序
[4, 2, 1, 4, 3].sort(function(a, b) { return a < b; });
// [4, 4, 3, 2, 1]

没问题,那我们再看一个例子:

1
2
3
4
// 将数组降序排序
[5, 5, 5, 5, 5, 5, 4, 5, 5, 5, 5, 5]
  .sort(function(a, b) { return a < b; });
// chrome [4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5]

Firefox和IE下结果正确,但是在chrome下结果大跌眼镜,4跑到最前面去了,这难道是chrome的bug吗?

V8排序的算法

于是我翻出V8引擎对数组排序实现的代码,研究了一番

监听DOM Tree

最近一个项目中需要监听DOM tree的改变,首先想到使用MutationObserver

不过发现在低版本的webkit里面并不支持该API。于是考虑使用Mutation events,查了一下资料虽然很多浏览器目前仍然支持Mutation events,但是在W3C的标准里它已被废弃,取而代之的就是之前提到的MutationObserver。关于Mutation events的问题,引用一段John Resig的描述:

Yes, DOM mutation events already exist (in Firefox and Opera – fairly reliably – and dicey in Safari). They have a huge problem, though:

They absolutely cripple DOM performance on any page which they’re enabled.

Firefox, for example, when it realizes that a mutation event has been turned on, instantly goes into an incredibly-slow code path where it has to fire events at every single DOM modification. This means that doing something like .innerHTML = “foo” where it wipes out 1000 elements would fire, at least 1000 + 1 events (1000 removal events, 1 addition event).

总而言之,Mutation events会带来很大的性能问题,所以我们似乎也不应该使用它,那么还有什么其他方法吗?

高效的山寨DOMNodeInserted事件

是的,还真有。我们可以利用CSS3的animationStart事件来模拟DOMNodeInserted事件。

具体方法是:
1. 给指定的元素添加一个非常短暂的关键帧动画,比如叫:nodeInserted
2. 监听animationStart事件
3. 通过事件的animationName属性过滤,找到我们关心的元素

由于有动画的元素相对较少,所以该方法的性能比Mutation events会高出不少,并且在所有支持的CSS3 animation的浏览器上都支持,怎么样?很酷吧!

HTML5物理引擎–Verlet.js

首先,让我们来看一个HTML5模拟的衣服效果:

很酷吧,要实现这样的效果想必很难吧?的确,如果没有框架的支持我们需要了解一些数学和运动学的基本知识。不过,下面我要隆重推出本文主角——

Verlet

它是一个开源的js物理引擎,相比于其他同类引擎,它有下面优势

  • 非常轻量级,未压缩的也不过不到700行
  • 相比其体积,它提供了强大的功能和良好的扩展性
  • 易用的API,类库内置了4种物理元素:点、线段、衣服(cloth)、多变型(tire)

(未完待续)

答题

下面是我对寒冬老师题目的答案。

1. 你对前端职业发展有何看法?

相比后端,前端具备更加丰富的知识结构,职业发展的方向应该更加广阔。但是选择多了,也可能会迷茫,再加上目前国内前端发展参差不齐,地域差异严重,主要机会都集中在北、上、杭、深等城市。所以,我的看法是首先争取进入一个优秀的团队,和优秀的人一起做事,不断提高自己;另外我认为无论是转管理,转产品还是一直做技术都不重要,重要的是你的职业生涯是往上走的。就我个人而言,未来两到三年内重心还是放在技术上面,希望能够完成一或几个自己满意的作品。

2. 前端和后端程序员应该如何合作?

前端要拥抱变化,而后端希望保持稳定,必然会有争执。作为前端开发,我们可以承担更多的职责。比如:在瘦服务器端的架构里面服务端只提供数据,页面的渲染和业务逻辑都由终端来完成;在Nodejs出现以后,前端的定义已经不局限在客户端,在平台不变的情况下,我们完全可以自己给自己搭一道桥来完成新的需求。同时,前端应该对平台的更新起到牵引作用。最后,不光是前后端,任何高效的团队合作都需要解耦,我们可以通过合理的接口定义划分好各自的职责,然后通过打桩等方式模拟接口实现,最后通过两两联调和集成测试来完成对接。

3. 讲几个你在项目中解决的让你印象最深的问题(难、匪夷所思、解决方案有趣都可以)

选了几个项目中遇到的问题分享给大家

浅谈display, Position, Float

display, position, float三者可以说是CSS布局里最基本也最常用的属性。在此对这三个属性的可选值以及互相叠加的效果做一个总结。

基本概念

position

通过该属性可以设置节点的定位方式,可选的值有:

  • absolute 绝对定位
    从文本流中抽离出来,单独生成一个“块级”盒子。该盒子的位置将相对于“显示定位”的父节点左上角来定位,如果没有“显示定位”的父节点就以body元素左上角为原点。

  • relative 相对定位
    相对定位是以元素“原来”位置的基础上来定位。元素在文本流中的原始位置会保留,不会被其他元素占据

  • static 正常文本流
    默认值,不定位

  • fixed 固定定位
    相对于浏览器的“视口”进行定位,视口大小不受文本流大小影响。

闭包总结

什么是“闭包”?

通俗讲闭包就是–定义在函数内部的函数可以访问外层作用域的变量。当然这只是闭包的表象,要理解闭包我们先要澄清两个容易混淆的概念。

执行环境(Execute Context)

当进入(开始执行)一段可执行代码时,便生成一个执行环境对象。

一个执行环境(Execute Context)包含三个要素:

  • 词法环境 – LexicalEnvironment
  • 变量环境 – VariableEnvironment
  • This绑定 - ThisBinding

注:词法环境在我理解就是所谓的“作用域”。

作用域(Scope)

JavaScript只有两种作用域(没有块级作用域)

  • 全局作用域:即全局可以访问的作用域,包括下面一些

    1. 最外层定义的变量和函数
    2. 未定义直接赋值的变量
    3. Global对象的属性
  • 局部作用域:只有固定代码片段可以访问,创建局部作用域(词法环境)的方式有

    1. 执行函数
    2. 执行Catch语句
    3. with

OPP in JavaScript

面向对象的设计思想是语言无关的。但是在实现上JavaScript和其他语言还是有些区别的。

对象的构造:

  • 字面量 可以用JSON风格直接构造一个对象,这是一种非常直接和简洁的对象创建方式。
1
2
3
4
5
6
7
var obj = {
  name: "Peter Gao",
  age: 29
};

obj.sex = "male";
delete obj.age;

  • 构造函数 和其他面向对象语言类似,我们可以使用new关键字加构造函数的方式来创建一个对象,在new A的时候JavaScript引擎做了下面几件事情:

    1. 创建一个新的对象
    2. 将对象的contructor属性设置为A
    3. 将A.prototype设置为新对象的原型
    4. 以新对象为上下文(context)执行A
  • Object.create 这是ECMAScript 5里面提供的一个新方法,通过这个方法我们可以直接指定对象的原型。甚至通过Object.create(null)我们可以创建一个没有原型的“干净”对象

第一章 动画基本概念

这一章包含那些内容呢?

  • 什么是动画?
  • 帧(Frames)和动作(motion)
  • 动态动画 vs 静态动画

浏览器从最开始获得互联网文本信息的工具,发展到今天已经逐渐演变成一个完全图像化,交互化的运行环境,迅速地颠覆了我们沟通和分享的方式。最新的HTML5标准中,加入了以前只能在native应用可用的图像处理能力。经过一段时期的停滞以后,现在浏览器正受益于新一轮HTML5,JavaScript等技术的革新。HTML5 canvas元素使我们能够创建标准的游戏,应用和动画,并且兼容各种标准浏览器和移动设备,包括目前流行的设计和平板(iPhone, iPad和Android设备)。

这本书囊括了使用HTML5 canvas元素和JavaScript构造动画效果的编程,数学和物理等各方面技术。你们将看到,那些绚丽的动画效果将首次在标准浏览器上得以实现。

在我们深入具体的技术和公式前,让我们首先很快的了解到底什么是动画?介绍一些它背后基础的概念,来帮助你创建更加有趣的动画效果

不管你是不是第一次接触或者已经有使用Adobe Flash等类似工具的经验,这本书都是你动画编程很好的指导。由于Flash向JavaScript的迁移,本书经历了多次改变,但是从另外一方面证明了底层的技术和数学概念是语言无关的。我们现在讨论的是web浏览器,但是只要适度的图像能力支持,这些公式和样例适用于各种编程环境。

当然,如果你已经迫不及待写点代码了,你也可以跳过本章。但是还是强烈建议你读一读,至少帮助你了解动画是如何工作的。

什么是动画?

简历

本人目前打算换工作,更新简历如下,欢迎有意者骚扰。Word版简历请猛戳这里

基本信息:

姓名:高晓晨(男)

生日:1984-05-10

学历:2006年毕业于北京邮电大学 软件工程专业 小本

联系方式:13540478015 | gxcsoccer@126.com

目前城市:南京

自己写一个seajs的打包工具

最近的项目中使用了玉伯的seajs。在项目归档的时候需要把上百个文件combine到一起,本来想用seajs配套的spm来做,但是看了看似乎有点复杂,索性自己写了一个小工具。

其实我们的需求比较简单:把通过require加载的js文件都打到一个文件里,而通过use加载的就不用了。

combine一般的js文件非常容易,只需要按照依赖顺序做文件的合并即可。但是对于型如:define(function(){ … })这样seajs风格文件这样显然是不行,浏览器会狂报404。那么应该如何做呢?

我们在使用define函数去定义一个模块时一般都只会传一个函数作为参数,实际上define函数有三个参数

  • id: 模块的标识,如果这个参数不传,会使用文件的url作为文件标识
  • deps: 依赖列表,如果这个参数不传,seajs会分析函数body找出依赖列表
  • body: 模块体