Archives for the ‘JavaScript’ Category

chrome下console的一个BUG

今天在chrome下调程序,用console.log打印对象信息想看变量值在执行过程中的变化,打印结果一直不对头。还以为是我的程序写得有问题,后来才发现原来chrome的console.log打印出来的信息一直是程序执行完的最后结果,而无法看到执行过程中的值。一搜,原来是webkit下的一个bug。
问题描述如下:

var obj = new Object();
obj.a = 1;
obj.b = 2;
console.log(obj);
delete obj.b;
console.log(obj);

意料中的结果应该是:

obj { a:1, b:2}
obj { a:1 }

但结果却是:

obj { a:1}
obj { a:1 }

在FF上打出来的结果是正常的,看来是chrome的问题。后来还是在stack overflow上找到了解答:Is Chrome’s JavaScript console lazy about evaluating arrays?。

it occurs when the code resides in scripts that are executed immediately (before the page is loaded), even when the console is open, whenever the page [...]

addEventListener对onclick做了什么

其实答案是:没有做什么。
发现问题的过程
为什么会想到这个问题,是因为在看PPK的讲Advanced event registration models的博文时,其中说到Microsoft model的一个drawback:
# The event handling function is referenced, not copied, so the this keyword always refers to the window and is completely useless.
又因为在他的另外一篇博文The this keyword里的copying examples写到
this is written into the onclick method in the following cases:
于是想到执行addEventListener/attachEvent的时候应该对元素的onclick属性做了什么,然后我可以通过查看元素的onclick属性来验证W3C的addEventListener是copy了函数给onclick而Microsoft的attachEvent则只是引用了函数。
但问题就来了,上面的验证思路行不通,因为我看不到执行addEventListener/attachEvent后onclick属性的任何变化。于是很好奇addEventListener难道没对onclick做任何处理?于是跑到stack overflow去提问,大牛们给了些指示,这里可以看到stack overflow上我的问题。
其实是关乎两个DOM模型的事
tvanfosson的回答提到:
OnClick is a DOM Level 0 property. AddEventListener is part of the DOM Level 2 [...]

《JavaScript设计模式》中的一个错误

中文版93页在介绍XHR工厂时,源代码是这样的:

createXhrObject: function() {
var methods = [
function() { return new XMLHttpRequest(); },
function() { return new ActiveXObject('Msxml2.XMLHTTP'); },
function() { return new ActiveXObject('Microsoft.XMLHTTP'); }
];
for (var i = 0, len = methods.length; i < len; ++i) {
try {
methods[i]();
}
catch (e) {
continue;
}
this.createXhrObject = method[i];
return methods[i];
}

throw new Error(’SimpleHandler: Could not create an XHR object.’);
}

return后的表达式应该是method[i]()。不然返回的是函数对象。
这是2009年1月第1版的情况,不知道英文原版以及后来再版有没有存在这个问题。

最近看的几篇JS文章

不错的一篇关于javascript-prototype继承
总结:
1. js的原型继承是引用原型,不是复制原型。所有子类对象中的原型成员实际是同一个。不解的地方是:obj.a(a是父类中的成员属性) = ‘a’的时候,改的是哪个地方的a?为什么不会影响到另一个继承了同一个父类的类中a成员的值?
2. 构造子类时,原型的构造函数不会被执行。当然如果想执行,可以在子类的构造函数中这样写:父类.call(this, arguments)。这是在《JavaScript设计模式》中看到的写法,没有实践过,但应该是正确的。
a.x = a = { }, 深入理解赋值表达式
by 玉伯@淘宝
总结:
The production AssignmentExpression : LeftHandSideExpression = AssignmentExpression is evaluated as follows:
1. Evaluate LeftHandSideExpression.
2. Evaluate AssignmentExpression.
3. Call GetValue(Result(2)).
4. Call PutValue(Result(1), Result(3)).
5. Return Result(3).

其实主要理解好这个规则,还有理解好JS中引用类型就行了。词法作用域的一个小例子这篇文章可以加深理解。
探索javascript中函数的执行顺序
by tenfyguo@tencent
总结:js引擎会对各种函数定义进行“预编译”,但预编译的范围只限于块代码内。
闭包应用实例
by 潘魏增@美团
总结:其中美团代码演示时提出的修改方法可以比较比较,第二和第三种方法其实本质上都是避免让赋予事件接口的函数对象中直接依赖闭包环境中的自由变量。
再探Javascript词法作用域
另外还参考了作用域链 词法作用域 与 闭包(一)
总结:
函数被调用执行的时候引擎解析过程:
1. 根据调用参数,创建调用对象,创建参数变量
2. 根据函数定义,创建函数内部定义的变量
3. 把调用对象挂到作用域链的头部
4. 执行函数,返回结果
函数在定义它们的作用域里运行,而不是在执行它们的作用域里运行。调用对象位于作用域链的前端,局部变量(在函数内部用var声明的变量)、函数参数及Arguments对象都在函数内的作用域中——这意味着它们隐藏了作用域链更上层的任何同名的属性。
Javascript中同名标识符优先级
总结:没什么好说的,直接看正文,纯属补补基础知识。
理解渐进增强(Progressive Enhancement)
by 玉伯@淘宝
总结:其实不是讲JS的,讲web开发中的Graceful Degradation和Progressive Enhancement。
还有两篇比较讲的比较深入的,是去哪儿的金埔大师写的:JavaScript闭包真经,JavaScript对象真经这两篇还没看完,有些并不好读懂,还得再好好理解。
JS的知识得恶补,很多平时都没注意到,也没去仔细研究过。估计得把《JavaScript权威指南》拿来好好看看。

一些jQuery的最佳实践

看了14 Helpful jQuery Tricks, Notes, and Best Practices原文,记下来一些平时常用的:

jQuery总是返回jQuery对象,像hide()之类的操作dom的方法也一样。提醒多用链式写法和注意缓存对象。
用find,或者指定Context
不用滥用$(this),直接用原生JS最好。(保持jQuery一致的代码风格和JS效率问题该如何平衡?)
$(document).ready(function() {})的简写
防止命名冲突3个方法:多库共存jQuery.noConflict(),用匿名函数function($){}(jQuery),jQuery(document).ready(function($) {}。(看jQuery API,好像后面两种方法都需要先调用jQuery.noConflict(),保证只能使用jQuery变量访问jQuery对象)
不要在each()里用$(’#id’)的选择器,会有多次遍历查找dom元素,效率极低。
用document.createDocumentFragment()来减少页面的DOM结构改变的次数、刷新的次数
jQuery1.4中可以将一个属性集对象作为attr()的参数

改变JS在IE中的执行顺序

JS在FF/IE中不同的执行顺序
应该算是常见的问题,但之前才发现到。题目比较抽象,直接看示例代码:
一个外部JS文件:test.js
var inner_var = 1;
alert(’inner_var: ‘ + inner_var);
现在有一个HTML片段:
<script>
document.write(’<script src=”test.js”><\/script>’);
alert(’outer’);
alert(typeof(inner_val));
</script>
这段代码在FF中执行的结果是:inner_val: 1, outer, number,完全按照我们设计时的意愿来,但是在IE中执行的结果成了这样:outer, undefined, inner_val: 1
关于这个的原因,比较多的说法是IE还没等test.js加载完,就先执行底下的语句了,也就是说JS在FF和IE中的执行顺序不同。
改变JS在IE中的执行顺序
总结三个解决这个问题的方法:
1、利用浏览器解析完一个完整的HTML标签再解析下一个的原理
即将script里的document.write()里的代码抽出来,写在外头,这样IE会等加载完这个test.js后,再去执行下面的script里的代码。即: