阳光男孩

Never give up!

Entries Tagged ‘JavaScript’

Hail to the King!那段JavaScript历史

0顶一下1995年,Brendan说服Netscape的老板说在netscape中需要一个属于自己的脚本语言,在考察了Scheme和Java之后,10天之内,Brendan实现了JavaScript引擎的基本原型。从1995年到现在,经历了浏览器大战,经历了Mozilla开源项目的故事,16年之后的昨天,Brendan将SpiderMonkey的Module Ownership转移给了Mozilla的Dave Mandelin。 So it is with gratitude and more than a bit of relief, afte...[阅读全文]

0
顶一下

1995年,Brendan说服Netscape的老板说在netscape中需要一个属于自己的脚本语言,在考察了Scheme和Java之后,10天之内,Brendan实现了JavaScript引擎的基本原型。从1995年到现在,经历了浏览器大战,经历了Mozilla开源项目的故事,16年之后的昨天,Brendan将SpiderMonkey的Module Ownership转移给了Mozilla的Dave Mandelin。

So it is with gratitude and more than a bit of relief, after a very long 16 years in full, 13 years open source, that I’m announcing the transfer of SpiderMonkey’s module ownership to @dmandelin.

—— Brendan Eich

为此,Brendan大神写了这样一篇博客——New JavaScript Engine Module Owner,给我们讲述了那一段牛x的JavaScript历史,里面充满了睿智的小段子,非常有趣。

96年的时候,Brendan和chouck将JavaScript的运行放到了非主线程中,于是当网页加载一段需要大量计算的 JavaScript代码时不会影响页面中其他元素的渲染,至今大家也在Firefox可以看到“slow script running”的对话框;

快进到2008年,Firefox 3成功发布,Mozilla的JS团队取得巨大的性能提升,当时主要竞争对手还是来自WebKit的JavaScriptCore引擎,之后又成功炮制 TraceMonkey,——一个基于类型优化的实时JIT引擎,是早于Chrome和V8的面世;

在2006年的时候,Brendan就接触到了V8团队,当时Brendan非常希望V8能够开源,并且完全可以想办法接入到Firefox中,甚至于替代Firefox的SpiderMonkey,而且当时Adobe正在考虑将Tamarin提交给Mozilla,用Brendan的话说就是多多益善,“the more the merrier”。当时正是JavaScript JIT前期探索阶段;

直到2008年V8才正式开源,Google对此很谨慎,以防打草惊蛇的提醒到微软。(配合这款引擎,Chrome应声而出)很明显,95年时候 “Netscape + Java kills Windows”的说法激怒了微软,最后什么结果大家也都知道了。不过历史同样重现,Chrome的刺激带来了微软的IE9和Chakra。

V8长达两年的绝密飞行“伤害”了JavaScript,意味着Apple和Mozilla需要自己探索陡峭的JS优化之路,不过后来借助V8的开源,这个难度大大降低。不过随着Mozilla放出TraceMonkey,Apple放出SquirrelFish,加上Chrome的V8,都向世人证明了JavaScript不再低效,不再是一个玩具语言,当然随着AJAX的流行,JavaScript变的越来越流行。

JavaScript的路依然漫长……

TraceMonkey面世左右,Dave Mandelin加入了Mozilla。新的篇章开始。

新的JIT技术不断出现,Mozilla将Webkit中的Method JIT融入SpiderMonkey,优化别名JaegerMonkey;更多优化全面的Benchmark出现,其实主要强调来自Mozilla的Kraken;

而V8也开始Phase II,Crankshaft面世,开始向类型优化JIT的方向前进;

传统的JavaScript GC方式也开始变革,Mozilla先提出来Compartment GC分配内存的方式;而以往粗暴需要Pause的Allocation模式开始向Incremental和Generational GC探索;

IonMonkey是Mozilla的下一代优化JIT引擎,会跟Crankshaft接近,更加优化类型推演,还包括inline function等多种优化手段

如Brendan所言,JavaScript的路还很漫长,不过充满希望

Dave在11年Velocity大会上的演讲稿非常值得一看

JavaScript历久弥新,相信他拥有更美好的未来,而Brendan永远是心中的JS大神。

Hail to the King!

 

Comments (6)

JS画线,有点原始,但是兼容所有浏览器!

1顶一下用Javascript画线的方法很多,有SVG,VML、canvas等,但是在现阶段,貌似这些方法都不能兼容所有浏览器。所以我还是用最原始的办法法写了一个画线方法。思路也很简单,就是用一个像素的DIV拼成一条线。 function line(startX, startY, endX, endY, container) { if (startX == endX) { if (startY > endY) { var tempY = startY; startY = endY; endY = tempY...[阅读全文]

1
顶一下

用Javascript画线的方法很多,有SVG,VML、canvas等,但是在现阶段,貌似这些方法都不能兼容所有浏览器。所以我还是用最原始的办法法写了一个画线方法。思路也很简单,就是用一个像素的DIV拼成一条线。

function line(startX, startY, endX, endY, container) {
if (startX == endX) {
if (startY > endY) {
var tempY = startY;
startY = endY;
endY = tempY;
}
for (var k = startY; k < endY; k++) {
createPoint(container, startX, k);
}
}
// y = ax + b
var a = (startY - endY) / (startX - endX);
var b = startY - ((startY - endY) / (startX - endX)) * startX;
if (Math.abs(startX - endX) > Math.abs(startY - endY)) {
if (startX > endX) {
var tempX = endX;
endX = startX;
startX = tempX;
}
var left = container.style.left;
var top = container.style.top;
for (var i = startX; i <= endX; i++) {
createPoint(container, i, a * i + b);
}
} else {
if (startY > endY) {
var tempY = startY;
startY = endY;
endY = tempY;
}
for (var j = startY; j <= endY; j++) {
createPoint(container, (j - b) / a, j);
}
}

}

function createPoint(container, x, y) {
var node = document.createElement(‘div’);
node.className = ’line’;
node.style.marginTop = y;
node.style.marginLeft = x;
container.appendChild(node);
}

复制打印

function line(startX, startY, endX, endY, container) {
if (startX == endX) {
if (startY > endY) {
var tempY = startY;
startY = endY;
endY = tempY;
}
for (var k = startY; k < endY; k++) {
createPoint(container, startX, k);
}
}
// y = ax + b
var a = (startY - endY) / (startX - endX);
var b = startY - ((startY - endY) / (startX - endX)) * startX;
if (Math.abs(startX - endX) > Math.abs(startY - endY)) {
if (startX > endX) {
var tempX = endX;
endX = startX;
startX = tempX;
}
var left = container.style.left;
var top = container.style.top;
for (var i = startX; i <= endX; i++) {
createPoint(container, i, a * i + b);
}
} else {
if (startY > endY) {
var tempY = startY;
startY = endY;
endY = tempY;
}
for (var j = startY; j <= endY; j++) {
createPoint(container, (j - b) / a, j);
}
}

}

function createPoint(container, x, y) {
var node = document.createElement(‘div’);
node.className = ’line’;
node.style.marginTop = y;
node.style.marginLeft = x;
container.appendChild(node);
}

 

当然还需要一段CSS来控制样式:
div.line {
position:absolute;
z-index:2;
width:1px;
height:1px;
font-size:1px;
background-color:#0000FF;
overflow:hidden;
}
div.line {
position:absolute;
z-index:2;
width:1px;
height:1px;
font-size:1px;
background-color:#0000FF;
overflow:hidden;
}
来一段HTML测试一下
<html>
<head>
<script type=”text/javascript” src=”../js/jsline.js”></script>
<script type=”text/javascript”>
function testLine() {
line(1, 2, 88, 88, document.getElementById(‘container’));
}
</script>
</head>
<body>
<div id=”container” style=”width:400px;height:400px;border:1px solid #000000;margin-left:50px”></div>
<input type=”button” value=”line” onclick=”testLine();”></input>
</body>
</html>
 

 

Comments (12)

JavaScript初学者应注意的七个细节

0顶一下每种语言都有它特别的地方,对于JavaScript来说,使用var就可以声明任意类型的变量,这门脚本语言看起来很简单,然而想要写出优雅的代码却是需要不断积累经验的。本文利列举了JavaScript初学者应该注意的七个细节,与大家分享。 一、简化代码 JavaScript定义对象和数组非常简单,我们想要创建一个对象,一般是这样写的: var car = new Object(); car.colour = ‘red’; car.w...[阅读全文]

0
顶一下

每种语言都有它特别的地方,对于JavaScript来说,使用var就可以声明任意类型的变量,这门脚本语言看起来很简单,然而想要写出优雅的代码却是需要不断积累经验的。本文利列举了JavaScript初学者应该注意的七个细节,与大家分享。

一、简化代码

JavaScript定义对象和数组非常简单,我们想要创建一个对象,一般是这样写的:

var car = new Object();

car.colour = ‘red’;

car.wheels = 4;

car.hubcaps = ‘spinning’;

car.age = 4;

下面的写法可以达到同样的效果:

var car = {

colour:’red’,

wheels:4,

hubcaps:’spinning’,

age:4

}

后面的写法要短得多,而且你不需要重复写对象名称。

另外对于数组同样有简洁的写法,过去我们声明数组是这样写的:

var moviesThatNeedBetterWriters = new Array(

‘Transformers’,'Transformers2′,’Avatar’,'Indiana Jones 4′

);

更简洁的写法是:

var moviesThatNeedBetterWriters = [

'Transformers','Transformers2','Avatar','Indiana Jones 4'

];

对于数组,还有关联数组这样一个特别的东西。 你会发现很多代码是这样定义对象的:

var car = new Array();

car['colour'] = ‘red’;

car['wheels'] = 4;

car['hubcaps'] = ‘spinning’;

car['age'] = 4;

这太疯狂了,不要觉得困惑,“关联数组”只是对象的一个别名而已。

另外一个简化代码的方法是使用三元运算符,举个例子:

var direction;

if(x < 200){

direction = 1;

} else {

direction = -1;

}

我们可以使用如下的代码替换这种写法:

var direction = x < 200 ? 1 : -1;

二、使用JSON作为数据格式

伟大的Douglas Crockford发明了JSON数据格式来存储数据,你可以使用原生的javascript方法来存储复杂的数据而不需要进行任何额外的转换,例如:

var band = {

“name”:”The Red Hot Chili Peppers”,

“members”:[

{

"name":"Anthony Kiedis",

"role":"lead vocals"

},

{

"name":"Michael 'Flea' Balzary",

"role":"bass guitar, trumpet, backing vocals"

},

{

"name":"Chad Smith",

"role":"drums,percussion"

},

{

"name":"John Frusciante",

"role":"Lead Guitar"

}

],

“year”:”2009″

}

你可以使用在JavaScript中直接使用JSON,甚至作为API返回的一种格式,在许多的API中被应用,例如:

<div id=”delicious”></div><script>

function delicious(o){

var out = ‘<ul>’;

for(var i=0;i<o.length;i++){

out += ‘<li><a href=”‘ + o[i].u + ‘”>’ +

o[i].d + ‘</a></li>’;

}

out += ‘</ul>’;

document.getElementById(‘delicious’).innerHTML = out;

}

</script>

<script src=”http://feeds.delicious.com/v2/json/codepo8/javascript?count=15& callback=delicious”></script>

这里调用delicious 的Web服务获取最新书签,以JSON格式返回,然后将它们显示成无序列表的形式。

从本质上讲,JSON是用于描述复杂的数据最轻量级的方式,而且直接它运行在浏览器中。 你甚至可以在PHP中调用 json_decode()函数来使用它。

三、尽量使用JavaScript原生函数

要找一组数字中的最大数,我们可能会写一个循环,例如:

var numbers = [3,342,23,22,124];

var max = 0;

for(var i=0;i<numbers.length;i++){

if(numbers[i] > max){

max = numbers[i];

}

}

alert(max);

其实,不用循环可以实现同样的功能:

var numbers = [3,342,23,22,124];

numbers.sort(function(a,b){return b – a});

alert(numbers[0]);

而最简洁的写法是:

Math.max(12,123,3,2,433,4); // returns 433

你甚至可以使用Math.max来检测浏览器支持哪个属性:

var scrollTop= Math.max(

doc.documentElement.scrollTop,

doc.body.scrollTop

);

如果你想给一个元素增加class样式,可能原始的写法是这样的:

function addclass(elm,newclass){

var c = elm.className;

elm.className = (c === ”) ? newclass : c+’ ‘+newclass;

而更优雅的写法是:

function addclass(elm,newclass){

var classes = elm.className.split(‘ ‘);

classes.push(newclass);

elm.className = classes.join(‘ ‘);

}

四、事件委托

事件是JavaScript非常重要的一部分。我们想给一个列表中的链接绑定点击事件,一般的做法是写一个循环,给每个链接对象绑定事件,HTML代码如下:

<h2>Great Web resources</h2>

<ul id=”resources”>

<li><a href=”http://opera.com/wsc”>Opera Web Standards Curriculum</a></li>

<li><a href=”http://sitepoint.com”>Sitepoint</a></li>

<li><a href=”http://alistapart.com”>A List Apart</a></li>

<li><a href=”http://yuiblog.com”>YUI Blog</a></li>

<li><a href=”http://blameitonthevoices.com”>Blame it on the voices</a></li>

<li><a href=”http://oddlyspecific.com”>Oddly specific</a></li>

</ul>

脚本如下:

// Classic event handling example

(function(){

var resources = document.getElementById(‘resources’);

var links = resources.getElementsByTagName(‘a’);

var all = links.length;

for(var i=0;i<all;i++){

// Attach a listener to each link

links[i].addEventListener(‘click’,handler,false);

};

function handler(e){

var x = e.target; // Get the link that was clicked

alert(x);

e.preventDefault();

};

})();

更合理的写法是只给列表的父对象绑定事件,代码如下:

(function(){

var resources = document.getElementById(‘resources’);

resources.addEventListener(‘click’,handler,false);

function handler(e){

var x = e.target; // get the link tha

if(x.nodeName.toLowerCase() === ‘a’){

alert(‘Event delegation:’ + x);

e.preventDefault();

}

};

})();

五、匿名函数

关于JavaScript的最头疼的事情之一是,它的变量没有特定的作用范围。 一般情况下,任何变量,函数,数组或对象都是全局性,这意味着在同一页上的其他脚本可以访问并覆盖它们。解决方法是把变量封装在一个匿名函数中。 例如,下面的定义将产生三个全局变量和和两个全局函数:

var name = ‘Chris’;

var age = ’34′;

var status = ‘single’;

function createMember(){

// [...]

}

function getMemberDetails(){

// [...]

}

封装后如下:

var myApplication = function(){

var name = ‘Chris’;

var age = ’34′;

var status = ‘single’;

return{

createMember:function(){

// [...]

},

getMemberDetails:function(){

// [...]

}

}

}();

// myApplication.createMember() and

// myApplication.getMemberDetails() now works.

这被称为单体模式,是JavaScript设计模式的一种,这种模式在YUI中用得非常多,改进的写法是:

var myApplication = function(){

var name = ‘Chris’;

var age = ’34′;

var status = ‘single’;

function createMember(){

// [...]

}

function getMemberDetails(){

// [...]

}

return{

create:createMember,

get:getMemberDetails

}

}();

//myApplication.get() and myApplication.create() now work.

六、代码可配置

你写的代码如果想让别人更容易进行使用或者修改,则需要可配置,解决方案是在你写的脚本中增加一个配置对象。要点如下:

1、在你的脚本中新增一个叫configuration的对象。

2、在配置对象中存放所有其它人可能想要去改变的东西,例如CSS的ID、class名称、语言等等。

3、返回这个对象,作为公共属性以便其它人可以进行重写。

七、代码兼容性

兼容性是初学者容易忽略的部分,通常学习Javascript的时候都是在某 个固定的浏览器中进行测试,而这个浏览器很有可能就是IE,这是非常致命的,因为目前几大主流浏览器中偏偏IE对标准的支持是最差的。最终用户看到的结果 也许就是,你写的代码在某个浏览器无法正确运行。你应该把你的代码在主流的浏览器中都测试一下,这也许很费时间,但是应该这样做。

 

Comments (53)