JAVASCRIPT

javascript里面的小数计算出现近似值的解决办法

在javascript里面,小数只能进行相似计算,例如:5.06+1.30,你得到的结果会是6.359999999999999,但有的小数计算又是正确的,如果计算出现了近似值,你可以用如下的方法计算:

var number1 = 5.06;
var number2 = 1.30;
var sum = (number1 * 100 + number2 * 100) / 100; //sum=6.36,不是一个近似值

这样计算可以得到一个准确的结果。

javascript代码优化

一、字符串的连接

通常我们进行字符串连接是这样的:

var veryLongMessage =
‘This is a long string that due to our strict line length limit of’ +
maxCharsPerLine +
‘ characters per line must be wrapped. ‘ +
percentWhoDislike +
‘% of engineers dislike this rule. The line length limit is for ‘ +
‘ style purposes, but we don’t want it to have a performance impact.’ +
‘ So the question is how should we do the wrapping?’;

可以用如下的数字代替:

var veryLongMessage =
['This is a long string that due to our strict line length limit of',
maxCharsPerLine,
' characters per line must be wrapped. ',
percentWhoDislike,
'% of engineers dislike this rule. The line length limit is for ',
' style purposes, but we don't want it to have a performance impact.',
' So the question is how should we do the wrapping?'
].join();

二、通过助手函数生成字符串

通过把字符串生成器传递到函数中来构造一个长字符串,要避免临时的String结果,例如,假设函数buildMenuItemHtml_ 需要用文字串(literal)和变量来构造String,并在内部使用了String构造器.而不是如下方式使用:
var strBuilder = [];
for (var i = 0, length = menuItems.length; i < length; i++) {
strBuilder.push(this.buildMenuItemHtml_(menuItems[i]));
}
var menuHtml = strBuilder.join();

推荐如下方式:

var strBuilder = [];
for (var i = 0, length = menuItems.length; i < length; i++) {
this.buildMenuItem_(menuItems[i], strBuilder);
}
var menuHtml = strBuilder.join();

三、定义类方法(Defining class methods)

下面的代码是低效率的,每生成一次baz.Bar对象,就会为其生成一个方法和闭包.
baz.Bar = function() {
// 构造函数, constructor body
this.foo = function() {
// 方法,method body
};
}

推荐方式是:
baz.Bar = function() {
// 构造函数,constructor body
};

baz.Bar.prototype.foo = function() {
//方法, method body
};

这种方式,不管有多少个baz.Bar对象生成,仅仅只建立一个方法foo且没有产生闭包.

四、初始化实例变量(Initializing instance variables)

在原型(prototype)上用值类型[value type](而不是引用类型[reference type])声明或初始化实例变量.这避免了在每次调用构造函数时运行不必要的初始化代码.(有些情况下是不能这样做的:实例变量的初始值依赖于构造参数或是在构造时的其它状态的变量(some other state at time of construction))
例子:
foo.Bar = function() {
this.prop1_ = 4;
this.prop2_ = true;
this.prop3_ = [];
this.prop4_ = ‘blah’;
};

推荐的写法:
foo.Bar = function() {
this.prop3_ = [];
};
foo.Bar.prototype.prop1_ = 4;
foo.Bar.prototype.prop2_ = true;
foo.Bar.prototype.prop4_ = ‘blah’;

五、避开闭包的陷阱(Avoiding pitfalls with closures)

闭包是JavaScript的一个强大且有用的特色;但是它有几个缺点:
1,它们是常见的内存泄漏源
2,生成闭包明显的比生成不是闭包的内部函数慢,比调用静态函数更慢.例如
function setupAlertTimeout() {
var msg = ‘Message to alert’;
window.setTimeout(function() { alert(msg); }, 100);
}

上面比下面的写法要慢:(上面的代码产生了闭包)
function setupAlertTimeout() {
window.setTimeout(function() {
var msg = ‘Message to alert’;
alert(msg);
}, 100);
}

上面比下面的写法要慢:
function alertMsg() {
var msg = ‘Message to alert’;
alert(msg);
}

function setupAlertTimeout() {
window.setTimeout(alertMsg, 100);
}

3,它们增加了变量的作用域(scope chain)的层次.当浏览器解析属性的时候,将会检查所有层次的作用域.见下面的例子:
var a = ‘a’;
function createFunctionWithClosure() {
var b = ‘b’;
return function () {
var c = ‘c’;
a;
b;
c;
};
}

var f = createFunctionWithClosure();
f();

当执行f方法的时候,引用a比引用b慢,引用b比引用c慢.
IE中闭包更多信息可以查看 IE+JScript Performance Recommendations Part 3: JavaScript Code inefficiencies

六、避免用with(Avoiding with)

在你代码中避免用with.它对性能有负面影响,因为它修改了作用域,在其它作用域查找变量的开销很大.

七、避免浏览器的内存泄露(Avoiding browser memory leaks)

内存泄露是web应用程序普遍存在的问题,它会产生巨大的性能危害(hit).随着浏览器内存使用增加,你的web应用程序,用户系统其它部分操作,将变的慢起来.大部分web应用程序的内存泄露是因为在 JavaScript脚本和Dom之间生成了循环引用(例如:javascript脚本和IE com结构之间,javascript脚本和Firefox xpcom结构之间)
下面是避免内存泄漏一些经验法则

使用事件系统关联事件处理函数(Use an event system for attaching event handlers)
大部分的循环引用模式[DOM 元素-->事件处理函数(event handler)-->闭包(closure scope)-->DOM元素].为了避免这个问题,可以用经过充分测试事件系统(event system)来关联事件处理函数(event handlers),例如:Google doctype,Dojo,JQuery
另外,在IE中使用用内联事件函数(inline event handlers)会导致另一种的类型的泄露.这不是通常的循环引用类型的泄露,而是由内部临时匿名脚本对象产生的泄露.详细信息,请看文章”DOM insertin Order Leak Model”和例子JavaScript Kit tutorial.

避免扩展(expando)属性
扩展(expando)属性是把任意JavaScript的属性附加的到DOM元素上,这是循环引用产生的根源.你可以不产生内存泄露来扩展 (expando)属性,但是这是很容易产生内存泄露的.泄露模式是[DOM元素–>扩展(via expando)–>中间对象(intermediary object)–>DOM元素].最好是避免使用用它们.如果你用到它们,仅可使用原始类型(primitive types)作为值.如果不是原始类型,当扩展(expando)属性不在使用的时候,要把它置为空.可以参考文章”Circular References”

Google Closure Compiler Javascript脚本压缩工具

Google发布了Google Closure Compilerjavascript脚本压缩工具,google提供了3种可使用的方式:

1、网页在线压缩

地址为:http://closure-compiler.appspot.com/,打开网页即可,粘贴上脚本,即可压缩代码了。以下为界面截图:

代码放在上面图片的红边矩形那里,上面//开头的是设置项,不要删掉了,如果你的脚本用到了另外一个脚本文件,可以在最上面的Add a URL处添加,因为它压缩不仅仅是缩短你的代码,还会重新编写你的代码,所以要确保代码语法正确。点击“Compile”按钮后,将提交到google后台压缩,压缩完成后会在右边显示压缩结果,也会出现一个链接下载压缩后的代码!

2、压缩服务API

使用此API可以直接提交要压缩的代码至google,它会返回结果给你。

<html>
  <body>
    <form action="http://closure-compiler.appspot.com/compile" method="POST">
    <p>Type JavaScript code to optimize here:</p>
    <textarea name="js_code" cols="50" rows="5">
    function hello(name) {
      // Greets the user
      alert('Hello, ' + name);
    }
    hello('New user');
    </textarea>
    <input type="hidden" name="compilation_level" value="WHITESPACE_ONLY">
    <input type="hidden" name="output_format" value="text">
    <input type="hidden" name="output_info" value="compiled_code">
    <br><br>
    <input type="submit" value="Optimize">
    </form>
  </body>
</html>

注意Form的action地址,还有后的hidden里面的参数,都是可以自定义的,更多API的介绍可以看这里:http://code.google.com/closure/compiler/docs/api-ref.html
以下为上面代码的界面截图:

3、使用Closure Compiler Application

一个java写的命令行程序,通过命令行直接压缩要压缩的文件,经常要压缩javascript脚本的话,这个是最方便的方式了。把程序(javascript脚本压缩工具)下载到本地后,命令行转到程序的文件夹下。假设你有一个javascript脚本文件F:\scripts\test.js,把压缩后的文件放到F:\scripts\test.min.js,命令行代码如下:

java -jar compiler.jar --js "F:\scripts\test.js" --js_output_file "F:\scripts\test.min.js"

更多命令行帮助可以使用以下命令查看:

java -jar compiler.jar --help

在Wordpress里面给代码高亮插件增加运行代码功能

wordpress中装上代码高亮插件后,我装的是这个代码高亮插件(SyntaxHighlighter Evolved),其它的代码高亮插件也是一样,大部分都是用的SyntaxHighlighter,包装了一下而已。这个插件有一个比较遗憾的地方,就是没有运行代码的功能,一段html,想很方便的显示代码的效果,还必须把代码copy出来、粘贴才能看到效果。把下面这段代码加入到里的主题文件里面,在html代码片段中,鼠标放在代码片段上的时候就会显示“运行代码”的按钮。主题需引用了jQuery,或者自己加个jQuery的引用也行。

■ 主题中带有jQuery的代码如下:

<!-代码高亮加“运行代码” start-->
<script>
function runcode(code_id){
	var win1=window.open();
	win1.document.open();
	win1.document.write(
		SyntaxHighlighter.utils.unindent(
			SyntaxHighlighter.utils.fixInputString(SyntaxHighlighter.vars.highlighters[code_id].originalCode)
			.replace(/&lt;/g, '<')
			.replace(/&gt;/g, '>')
			.replace(/&amp;/g, '&')
		)
	);
	win1.document.close();
}
jQuery("div[class=syntaxhighlighter  xml]").live("mouseover", function(){
	if(jQuery(".runcode", this).length==0)
		jQuery(".toolbar", this).prepend('<a href="javascript:void(0);" onclick="runcode(jQuery(this).parent().parent().parent().attr(\'id\'))" class="item runcode" style="font-size:12px; width:48px; height:16px; text-indent:0px !important; line-height:16px; margin-top:0px !important;">运行代码</a>');
});
</script>
<!-代码高亮加“运行代码” end-->

■ 主题中不带有jQuery的代码如下:

<!-代码高亮加“运行代码” start-->
<script type="text/javascript" src="修改为你的jquery文件的路径"></script>
<script>
function runcode(code_id){
	var win1=window.open();
	win1.document.open();
	win1.document.write(
		SyntaxHighlighter.utils.unindent(
			SyntaxHighlighter.utils.fixInputString(SyntaxHighlighter.vars.highlighters[code_id].originalCode)
			.replace(/&lt;/g, '<')
			.replace(/&gt;/g, '>')
			.replace(/&amp;/g, '&')
		)
	);
	win1.document.close();
}
jQuery("div[class=syntaxhighlighter  xml]").live("mouseover", function(){
	if(jQuery(".runcode", this).length==0)
		jQuery(".toolbar", this).prepend('<a href="javascript:void(0);" onclick="runcode(jQuery(this).parent().parent().parent().attr(\'id\'))" class="item runcode" style="font-size:12px; width:48px; height:16px; text-indent:0px !important; line-height:16px; margin-top:0px !important;">运行代码</a>');
});
</script>
<!-代码高亮加“运行代码” end-->

javascript取窗口的可视高度和页面的内容高度

用javascript在不同的浏览器中取窗口的可视高度和页面的内容高度是个烦心的事,所用的html标准不同、页面的内容高度是否超过窗口的可视高度都会对取值产生影响,所用到的取值方法也不同。

一、取窗口的可视高度(即浏览器的上面的工具栏到下面的状态栏之间的高度)

1、IE中的取法

document.getElementsByTagName("html")[0].offsetHeight;

2、Firefox、Chrome、Opera中取法

window.innerHeight;

二、取页面内容的高度(所有浏览器中的取法)

Math.max(document.getElementsByTagName("body")[0].scrollHeight, 窗口的可视高度)

三、完整的代码如下:

//窗口的可视高度
var windowHeight=document.all ? document.getElementsByTagName("html")[0].offsetHeight : window.innerHeight;
//页面的内容高度
var pageHeight=Math.max(windowHeight, document.getElementsByTagName("body")[0].scrollHeight);

jquery插件实现图片延迟加载

前几天上QQ的在线视频网站,看到上面的影片列表页的图片有这样一种效果:当向下拉动滚动条时下面的图片才开始加载,就是说它不会一下子把所有的图片都加载出来,拉动滚动条后用户看到了才会显示,这是一个很不错的用户体验。减少了页面加载的时间了,也减轻了服务器的压力,看了一下javascript源码,里面写的了lazyload,我就百度了一下,找到了一个jquery的实现这种效果的插件:jquery.lazyload,一个很不错的插件。

比如你打开一个比较大或者长的网页,那么Lazy load能够实现先加载您所看到区域的图片,等你滚动到哪里,就加载那里的图片。

如果你是图片网站,而且一个页面要加载很多图片,这个插件是个很不错的选择。

如何使用,引用如下js:

<script src="jquery.js" type="text/javascript"></script>
<script src="jquery.lazyload.js" type="text/javascript"></script>

在你的页面中加入如下的javascript:

$("img").lazyload();

这将会使所有的图片都延迟加载。插件还有几个配置项可供设置。

当然对于一些用户来说就上面的功能远远是不能达到要求的,下面我们看看是如何设置灵敏度的。我们可以设置阀值来控制 这个功能比较人性化吧。

$(“img”).lazyload({ threshold : 200 });

把阀值设置成200 意思就是当图片没有看到之前先load 200像素。当然了你也可以通过设置占位符图片和自定事件来触发加载图片事件

$("img").lazyload({
	placeholder : "img/grey.gif",
	event : "click"
});

我们还可以通过定义effect 参数来定义一些图片显示效果

$("img").lazyload({
	placeholder : "img/grey.gif",
	effect : "fadeIn"
});

下载地址: source, minified or packed

用jQuery和jQuery UI做的自定义404页面

用jQuery和jQuery UI做的404错误页面效果,裂开和振动的效果,蛮逼真的,点击下面的图片查看效果:

HTML & CSS

首先建一个简单的html页面,当然你自己运用这个404页面的时候可以加一些自己的东西,例如,网站首页链接、网站导航等,这里我们为了演示就简单些了:

<html>
<head>
    <title>404 - File Not Found - Reynoldsftw.com</title>
    <script src="js/jquery-1.3.2.min.js"></script>
    <script src="js/jquery-ui-1.7.2.custom.min.js"></script>
    <script src="js/jquery-background.js"></script>
    <script src="js/controller.js"></script>
    <LINK href="css/style.css" rel="stylesheet" type="text/css">
</head>
<body>
    <div id="error_code">404</div>
    <div id="error_status">File Not Found</div>
    <div id="error_message">We're sorry you are seeing this page, please don't break the site again!</div>
    <div id="crack"></div>
    <div id="crack_overlay"></div>
</body>
</html>
有几个DIV里面放文本内容,两个空的DIV将会放图片。一个是裂开的图片,一个是用于覆盖在第一个图片上面的PNG图片,下面是这两个图片DIV的CSS样式:
#crack{z-index:1;position:absolute;width:200px;height:600px;background-image:url(../images/crack.png);left:520px;top:0px;}
#crack_overlay{z-index:1000;position:absolute;width:200px;height:600px;background-image:url(../images/crack_over.png);background-position:0px-1100px;left:520px;top:0px;}</div>

这里要注意:覆盖层的z-index要比其它的层大,这样才能遮住其它的层。

jQuery and jQuery UI

这里用到了jQuery UI里面的”shake”,”bounce”和”pulsate”效果。这里把效果的速度设置的比较小,为了看起来效果更好,这里用了随机的间隔时间。

var coord = -1125;

$(document).ready(function() {
	setTimeout("shake()", 2000);
});

function reveal()
{
	setTimeout("moreCrack(coord)", 200);
}

function shake()
{
	coordcoord = coord + 50;
	if(coord < -125)
	{
		$("#crack").effect("shake", {distance: 1}, 40, reveal);
		$("#error_code").effect("bounce", {distance: 5}, 50);
		$("#error_status").effect("pulsate", {times: 2}, 50);
	} else {
		$("#crack_overlay").hide();
	}
}

function randomXToY(minVal,maxVal,floatVal)
{
	var randVal = minVal+(Math.random()*(maxVal-minVal));
	return typeof floatVal=='undefined'?Math.round(randVal):randVal.toFixed(floatVal);
}

function moreCrack(coord)
{
	$("#crack_overlay").animate({backgroundPosition:"(0 " + coord + ")"});
	setTimeout("shake()", randomXToY(3500, 5000));
}

下载源码包

GreaseMonkey脚本:显示每个网站的收录数和外链数及PR、Alexa

更新:
2010-02-02 : 修正了有的设置项无效的bug
2009-10-16 : 全面重写代码,设置选项更丰富,可设查询项,可设是否自动启动,可设快捷键(初始快捷键F9);alexa加入昨日排名、一周平均和三月平均;百度加入首页快照日期、首页在百度中的位置;PR并入Google项;感谢jok的建议!
2009-09-18 : 修正Alexa显示的问题(alexa网站改变了html),同时加入脚本更新功能,点击右上角的问号即可查看脚本是否有新版本
2009-09-11 : 修正获取PR出现乱码的问题
2009-09-07 : 增加排除sogou页面的指令,以前忘记排除,以至于输入sogou的验证码老是提示错误
2009-09-01 : 优化显示效果,改为圆角矩形
2009-08-28:修改显示的CSS样式,保证在某些网站不变形
2009-08-23:加入PR和Alexa显示

前段时间总是折腾firefox,装上一些插件后,感觉使用起来很不错,装上了GreaseMonkey,就可以随心所欲的折腾当前打开的网页了,可惜没研究过firefox的插件是怎么做的,但用GreaseMonkey写上几个脚本还是很容易的。其实就是javascript脚本,但可以用GM里面内置的几个方法。那个向任何链接发起请求的方法很爽,不会出现跨域问题了,也不用使用代理页面来发起请求了,直接就可以获取任何链接的源码,但也出现了一个编码的问题,gb2312的页面有时候会出现中文乱码的问题,比较头疼。

今天发一个显示每个网站的收录数和外链数、还有PR、Alexa的脚本。安装脚本后会在每个页面的右上角显示这些信息,包括的搜索引擎有百度、谷歌、雅虎、搜狗、搜搜、有道和必应。搜狗的查询次数多了的话会提示输入验证码,这个会有提示的,点击链接进去输入验证码就OK了。脚本已经发布到userscripts.org(一个专门发布GM脚本的网站),脚本链接地址:http://userscripts.org/scripts/show/56095,点击进去后会有安装按钮或者直接点击此处安装,安装后就可以使用了,当然前提是你已经安装了GreaseMonkey,脚本源码地址:http://userscripts.org/scripts/review/56095。欢迎提出建议!以下为显示效果:

Internet Explorer 无法打开 Internet 站点xxx 已中止操作的解决办法

某些时候用IE打开页面时出现如下的错误警告窗口:

—————————
Windows Internet Explorer
—————————
Internet Explorer 无法打开 Internet 站点
http://www.junstyle.com.cn

已中止操作

—————————
确定
—————————

当点击确定页面就无法打开了,出现了一个错误的页面。这可能是因为你的javascript脚本在页面还没有载入完毕的时候改变了dom的结构,也就是用appendChild()向body里面添加了内容(子元素),导致body的结构错误,IE就无法显示网页了,当然在firefox中不会出现这个错误,一切正常。在IE中错误的用了如下的方法:

<!DOCTYPE html public "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<body>
	<div>
	<script type="text/javascript">
	document.body.appendChild(document.createElement("div"));
	</script>
	</div>
</body>
</html>

你可以用如下代码代替这个添加div的操作:

document.body.insertBefore(document.createElement(&amp;quot;div&amp;quot;), document.body.childNodes[0]);

使用insertBefore方法就不会出现前面的那个错误。

一步步学习调用Google Map Api(三):自定义地图类型

使用google map提供的api可以实现自定义地图类型,如显示卫星地图、街景地图等,这几个地图类型都是google内置的几种地图,当然你也可以自定义一种地图类 型,如路况、自己的地铁线路等地图信息,下面我们用google的地图数据来讲一下自定义地图类型的使用方法。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
<head>
	<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
	<title>Google 地图 JavaScript API 示例: 简单的地图</title>
	<script src="http://ditu.google.cn/maps?file=api&amp;v=2&amp;key=ABQIAAAAzr2EBOXUKnm_jVnk0OJI7xSosDVG8KKPE1-m51RBrvYughuyMxQ-i1QfUnH94QxWIa6N4U6MouMmBA&amp;hl=zh-CN" type="text/javascript"></script>
	<script type="text/javascript">
	function initialize() {
		var baseTileLayer = new GTileLayer(null, 12, 19);
		baseTileLayer.getTileUrl = function(tile, zoom){return "http://mt2.google.cn/mt/v=cn1.11&amp;hl=zh-CN&amp;s=Galileo&amp;x="+tile.x+"&amp;y="+tile.y+"&amp;z="+zoom;};
		var baseMapType = new GMapType([baseTileLayer], new GMercatorProjection(23), "自定义地图", {shortName: "自定义地图", alt: "自定义地图,junstyle"});

		var map = new GMap2(document.getElementById("map_container"), {mapTypes:[baseMapType]});
		map.addControl(new GLargeMapControl());
		map.addControl(new GScaleControl());
		map.setCenter(new GLatLng(39.917, 116.397), 14);
	}
	</script>
</head>
<body onload="initialize()" onunload="GUnload()">
	<div id="map_container" style="width: 500px; height: 300px"></div>
</body>
</html>

1、先定义一个平铺层var baseTileLayer = new GTileLayer(null, 12, 19); 第一个参数版权信息这里设为null,可以自己new一个,12表示最小缩放级别,19表示最大缩放级别。 baseTileLayer.getTileUrl = function(tile, zoom){return “http://mt2.google.cn/mt/v=cn1.11&hl=zh-CN&s=Galileo& x=”+tile.x+”&y=”+tile.y+”&z=”+zoom;},然后设置getTileUrl这个属性,它是一个方法,来 获取用于平铺层的图片地址,这个地址是根据缩放级别和经纬度来确定的,我这里调用的是google的图片数据,用的是google的链接。你如果要弄自己 的自定义地图,那就需要调用自己的图片了,这里比较重要。

2、定义一个地图类型。var baseMapType = new GMapType([baseTileLayer], new GMercatorProjection(23), “自定义地图”, {shortName: “自定义地图”, alt: “自定义地图,junstyle”}),把baseTileLayer作为参数传给它。

3、定义地图了。和以前定义地图差不多,但多了一个参数:{mapTypes:[baseMapType]},就是第二步定义的mapType。

这样一个自定义地图类型就完成了。