解析 Array.prototype.slice.call(arguments)

2011年12月23日 汪小俊 没有评论

转自:博客园

1。Array.prototype:就是Array的原型,很多时候理解这个原型有点不清不楚的

其实,有点像.NET里的反射

一个类凡是通过prototype加的属性,方法,都可以在这个类的对象里找到 对象.

有时候我们也直接在某一对象添加属性方法,那么只能这个对象里找到,重新创建的对象是没有

刚刚在上一对象里添加的属性方法的

内置的类型可以通过prototype找到内置的属性方法

Array.prototype.slice这句就是访问Array的内置方法

因为Array是类名,而不是对象名,所以不能直接用Array.slice

 

2。接下来说slice方法,这个简单

返回一个数组的一段。arrayObj.slice(start, [end]) 参数开始索引和结束索引,结束索引可以省略

3。call方法

call([thisObj[,arg1[arg2[[argN]]]]])

调用一个对象的一个方法,以另一个对象替换当前对象

thisObj
可选项。将被用作当前对象的对象。
arg1, arg2, , argN
可选项。将被传递方法参数序列。

说明

call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。

如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj

这东西JS文档里我没找到怎么调用这个方法,功能是 调用一个对象的一个方法 自己的参数只有方法的所有者对象和要调用的方法参数,

查过资料才知道,Array.prototype.slice.call 是这么调用,只要 typesof fn ===”function” 的 fn类型都有 call 方法

伪组数元素

call 方法以另一个对象替换当前对象
thisObj 可选项。将被用作当前对象的对象。
这就是说:Array.prototype.slice.call(arguments,0) 这句里,就是把 arguments 当做当前对象
也就是说 要调用的是 arguments 的slice 方法,后面的 参数 0 也就成了 slice 的第一个参数slice(0)就是获取所有

为什么要这么调用 arguments 的slice 方法呢?就是因为 arguments 不是真的组数,typeof arguments===”Object” 而不是 “Array”

它没有slice这个方法,通过这么Array.prototype.slice.call调用,JS的内部机制应该是 把arguments对象转化为Array

因为Array.prototype.slice.call调用后,返回的是一个组数

经典例子:

function classA() {
    this.name='bluedestiny';
    this.show = function () {
        alert(this.name);
    }
}
function classB() {
    this.name = 'never-online';
}
 
var objA = new classA();
var objB = new classB();
 
objA.show.call(objB);

跟call类似的还有 apply 方法

应用某一对象的一个方法,用另一个对象替换当前对象。

<strong>apply([thisObj[,argArray]])</strong>

参数

thisObj
可选项。将被用作当前对象的对象。
argArray
可选项。将被传递给该函数的参数数组。

说明

如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。

如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数。

呵呵,这么火星的功能,实在是少见啊,估计也就是JS里

 两者的区别: 对于apply和call两者在作用上是相同的,但两者在参数上有区别的。
对于第一个参数意义都一样,但对第二个参数:
apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入,而call则作为call的参数传入(从第二个参数开始)。
如 func.call(func1,var1,var2,var3)对应的apply写法为:func.apply(func1,[var1,var2,var3])

同时使用apply的好处是可以直接将当前函数的arguments对象作为apply的第二个参数传入

分类: Javascript 标签: ,

JavaScript SandBox设计模式

2011年12月23日 汪小俊 没有评论

原文转自:简明现代魔法

沙箱模式常见于YUI3 core,它是一种采用同一构造器(Constructor)生成彼此独立且互不干扰(self-contained)的实例对象,而从避免污染全局对象的方法。

命名空间

JavaScript本身中没有提供命名空间机制,所以为了避免不同函数、对象以及变量名对全局空间的污染,通常的做法是为你的应用程序或者库创建一个唯一的全局对象,然后将所有方法与属性添加到这个对象上。

代码清单1 : 传统命名空间模式

/* BEFORE: 5 globals */
// constructors
function Parent() {}
function Child() {}
// a variable
var some_var = 1;
// some objects
var module1 = {};
module1.data = {a: 1, b: 2};
var module2 = {};
/* AFTER: 1 global */
// global object
var MYAPP = {};
// constructors
MYAPP.Parent = function() {};
MYAPP.Child = function() {};
// a variable
MYAPP.some_var = 1;
// an object
MYAPP.modules = {};
// nested objects
MYAPP.modules.module1 = {};
MYAPP.modules.module1.data = {a: 1, b: 2};
MYAPP.modules.module2 = {};

在这段代码中,你创建了一个全局对象MYAPP,并将其他所有对象、函数作为属性附加到MYAPP上。

通常这是一种较好的避免命名冲突的方法,它被应用在很多项目中,但这种方法有一些缺点。

  • 需要给所有需要添加的函数、变量加上前缀。
  • 因为只有一个全局对象,这意味着一部分代码可以肆意地修改全局对象而导致其余代码的被动更新。

全局构造器

你可以用一个全局构造器,而不是一个全局对象,我们给这个构造器起名为Sandbox(),你可以用这个构造器创建对象,你还可以为构造器传递一个回调函数作为参数,这个回调函数就是你存放代码的独立沙箱环境。

代码清单2:沙箱的使用

new Sandbox(function(box){
	// your code here...
});

让我们给沙箱添加点别的特性。

  1. 创建沙箱时可以不使用’new’操作符。
  2. Sandbox()构造器接受一些额外的配置参数,这些参数定义了生成对象所需模块的名称,我们希望代码更加模块化。

拥有了以上特性后,让我们看看怎样初始化一个对象。

代码清单3显示了你可以在不需要‘new’操作符的情况下,创建一个调用了’ajax’和’event’模块的对象。

代码清单3:以数组的形式传递模块名

Sandbox(['ajax', 'event'], function(box){
	// console.log(box);
});

代码清单4:以独立的参数形式传递模块名

Sandbox('ajax', 'dom', function(box){
	// console.log(box);
});

代码清单5显示了你可以把通配符’*'作为参数传递给构造器,这意味着调用所有可用的模块,为了方便起见,如果没有向构造器传递任何模块名作为参数,构造器会把’*'作为缺省参数传入。

代码清单5:调用所用可用模块

Sandbox('*', function(box){
	// console.log(box);
});
 
Sandbox(function(box){
	// console.log(box);
});

代码清单6显示你可以初始化沙箱对象多次,甚至你可以嵌套它们,而不用担心彼此间会产生任何冲突。
代码清单6:嵌套的沙箱实例

Sandbox('dom', 'event', function(box){
	// work with dom and event
	Sandbox('ajax', function(box) {
	// another sandboxed "box" object
	// this "box" is not the same as
	// the "box" outside this function
	//...
	// done with Ajax
	});
	// no trace of Ajax module here
});

从上面这些示例可以看出,使用沙箱模式,通过把所有代码逻辑包裹在一个回调函数中,你根据所需模块的不同生成不同的实例,而这些实例彼此互不干扰独立的工作着,从而保护了全局命名空间。

阅读全文…

JavaScript跨域总结与解决办法

2011年12月1日 汪小俊 没有评论

转自博客园:http://www.cnblogs.com/rainman/archive/2011/02/20/1959325.html

什么是跨域

JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象。但在安全限制的同时也给注入iframe或是ajax应用上带来了不少麻烦。这里把涉及到跨域的一些问题简单地整理一下:

首先什么是跨域,简单地理解就是因为JavaScript同源策略的限制,a.com 域名下的js无法操作b.com或是c.a.com域名下的对象。更详细的说明可以看下表:

URL 说明 是否允许通信
http://www.a.com/a.js

http://www.a.com/b.js

同一域名下 允许
http://www.a.com/lab/a.js

http://www.a.com/script/b.js

同一域名下不同文件夹 允许
http://www.a.com:8000/a.js

http://www.a.com/b.js

同一域名,不同端口 不允许
http://www.a.com/a.js

https://www.a.com/b.js

同一域名,不同协议 不允许
http://www.a.com/a.js

http://70.32.92.74/b.js

域名和域名对应ip 不允许
http://www.a.com/a.js

http://script.a.com/b.js

主域相同,子域不同 不允许
http://www.a.com/a.js

http://a.com/b.js

同一域名,不同二级域名(同上) 不允许(cookie这种情况下也不允许访问)
http://www.cnblogs.com/a.js

http://www.a.com/b.js

不同域名 不允许
特别注意两点:
第一,如果是协议和端口造成的跨域问题“前台”是无能为力的,
第二:在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。
“URL的首部”指window.location.protocol +window.location.host,也可以理解为“Domains, protocols and ports must match”。

接下来简单地总结一下在“前台”一般处理跨域的办法,后台proxy这种方案牵涉到后台配置,这里就不阐述了,有兴趣的可以看看yahoo的这篇文章:《JavaScript: Use a Web Proxy for Cross-Domain XMLHttpRequest Calls

1、document.domain+iframe的设置

对于主域相同而子域不同的例子,可以通过设置document.domain的办法来解决。具体的做法是可以在http://www.a.com/a.html和http://script.a.com/b.html两个文件中分别加上document.domain = ‘a.com’;然后通过a.html文件中创建一个iframe,去控制iframe的contentDocument,这样两个js文件之间就可以“交互”了。当然这种办法只能解决主域相同而二级域名不同的情况,如果你异想天开的把script.a.com的domian设为alibaba.com那显然是会报错地!代码如下:

www.a.com上的a.html

document.domain = 'a.com';
var ifr = document.createElement('iframe');
ifr.src = 'http://script.a.com/b.html';
ifr.style.display = 'none';
document.body.appendChild(ifr);
ifr.onload = function(){
    var doc = ifr.contentDocument || ifr.contentWindow.document;
    // 在这里操纵b.html
    alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue);
};

script.a.com上的b.html

document.domain = 'a.com';

这种方式适用于{www.kuqin.com, kuqin.com, script.kuqin.com, css.kuqin.com}中的任何页面相互通信。

备注:某一页面的domain默认等于window.location.hostname。主域名是不带www的域名,例如a.com,主域名前面带前缀的通常都为二级域名或多级域名,例如www.a.com其实是二级域名。 domain只能设置为主域名,不可以在b.a.com中将domain设置为c.a.com。

问题:
1、安全性,当一个站点(b.a.com)被攻击后,另一个站点(c.a.com)会引起安全漏洞。
2、如果一个页面中引入多个iframe,要想能够操作所有iframe,必须都得设置相同domain。

2、动态创建script

虽然浏览器默认禁止了跨域访问,但并不禁止在页面中引用其他域的JS文件,并可以自由执行引入的JS文件中的function(包括操作cookie、Dom等等)。根据这一点,可以方便地通过创建script节点的方法来实现完全跨域的通信。具体的做法可以参考YUI的Get Utility

这里判断script节点加载完毕还是蛮有意思的:ie只能通过script的readystatechange属性,其它浏览器是script的load事件。以下是部分判断script加载完毕的方法。

js.onload = js.onreadystatechange = function() {
    if (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') {
        // callback在此处执行
        js.onload = js.onreadystatechange = null;
    }
};
 阅读全文...
分类: Javascript 标签: ,

如何判断oracel安装成功

2011年12月1日 汪小俊 1 条评论

转自:百度空间 , CSDN

要测试数据安装是否成功,可按顺序执行以下两个步骤: 
测试步骤 1请执行操作系统级的命令:tnsping orcl 
上述命令假定全局数据库名是 orcl。以下是命令执行后的示例:
C:\>tnsping orcl

TNS Ping Utility for 32-bit Windows: Version 10.2.0.1.0 – Production on 10-11-2005 10:09:58

Copyright (c) 1997, 2005, Oracle. All rights reserved.

已使用的参数文件:
C:\oracle\product\10.2.0\db_1\network\admin\sqlnet.ora

已使用 TNSNAMES 适配器来解析别名
Attempting to contact (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = dbserver
)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = orcl)))
OK (50 毫秒)

其中,结果 OK 至关重要。 上述结果如果正确,表明侦听器配置无误。 
如果没有看到此结果,不要继续进行下一步。请检查: 
使用 Oracle Net Configuration Assistant 检查网络配置(netca 命令) 使用 Database Configuration Assistant 检查数据库配置(dbca 命令) 测试步骤 2请执行操作系统级的命令:sqlplus system/password@orcl 
上述命令假定 SYSTEM 用户对应的口令是 password,假定全局数据库名是 orcl。 
以下是命令执行后的示例(请手工输入红色部分文字): 
C:\>sqlplus system/password@orcl

SQL*Plus: Release 10.2.0.1.0 – Production on 星期四 11 10 10:15:25 2005

Copyright (c) 1982, 2005, Oracle. All rights reserved.

连接到:
Oracle Database 10g Release 10.2.0.1.0 – Production

SQL> SELECT 1+2+3+4 测试结果 FROM DUAL; 

测试结果
———-
10

顺便附上oracel的默认用户名/密码

 

用户名 / 密码 登录身份 说明
sys/change_on_install SYSDBA 或 SYSOPER 不能以 NORMAL 登录,可作为默认的系统管理员
system/manager SYSDBA 或 NORMAL 不能以 SYSOPER 登录,可作为默认的系统管理员
sysman/oem_temp   sysman 为 oms 的用户名
scott/tiger NORMAL 普通用户
aqadm /aqadm SYSDBA 或 NORMAL 高级队列管理员
Dbsnmp/dbsnmp SYSDBA 或 NORMAL 复制管理员
分类: java 标签: ,

高性能javascript 学习笔记四

2011年11月30日 汪小俊 没有评论

这篇我想写下关于javascript的其他优化,很杂,这整个四篇只能说描述了javascript的皮毛,javascript可以说是简约而不简单,还是有很多方面值得我们去学习的地方。一下写的有些是总结某些大神博客上的内容,哈哈,人家这么精辟的总结当然要好好分享~

1.DOM操作

总所周知,DOM是个和语言无关的API,在浏览器中这个API 由JavaScript实现。

浏览器中DOM JS 会分别实现。

比如 IE: js–JScript–jscript.dll    DOM另外一个库-mshtml.dll(Trident)

这中分离允许其他语言比如VBScript共享DOM及其Trident提供的渲染函数。

Chrome的DOM用的是Webkit中的WebCore,js是V8引擎。等等 其他浏览器都是二者分离的。

二者分离 好处可能是复用接口

坏处 性能问题。DOM JS两个岛屿上,js访问DOM每次都要过桥,次数多了 性能有问题。

解决办法:尽量少过桥,尽量在js上解决问题。

关于js中innerhTML方法和普通DOM操作(例:document.creatElement)的比较

书本中说效率没有太大的区别,只是用户习惯上的差距,本人比较习惯使用innerhTML(jquery中的text()/html())方法,不多废话,上几个小例子,用上 笔记一中写上的测试代码来验证验证

例一:

function innerHtmlLoop(){
	var div=document.getElementById('test');
	for(var count=0;count&lt;15000;count++){
		div.innerHTML+='a';
	}
}

在IE8下用时:6.3s      在火狐7上用时:3.2s     在chrome上用时:10s(也验证了chrome对普通DOM操作更好的支持)

例二:

function innerHtmlLoop(){
	var div=document.getElementById('test');
	var html='';
	for(var count=0;count&lt;15000;count++){
		html+='a';
	}
	div.innerHTML=html;
}

在IE8下用时:16ms   在火狐7上用时:2ms      在chrome上用时:4ms

效率是千倍的增长,在内容比较长的时候,建议大家用数组来存储字符串,性能会得到最佳的提升!

阅读全文…

高性能javascript 学习笔记三

2011年11月29日 汪小俊 没有评论

这篇文章我想和大家分享一下javascript中作用域(链)的知识

首先,这是对JS数据访问的小结,写在前面,这是某位大神的总结,我就不吝啬的自己写了

在JavaScript中,数据存储的位置会对代码整体性能产生重大的影响。数据存储共有4种方式:直接量、变量、数组项、对象成员。它们有不同的性能考虑。

  1. 访问直接量和局部变量的速度最快,相反,访问数组元素和对象成员相对较慢。
  2. 由于局部变量存在于作用域链的起始位置,因此访问局部变量比访问跨作用域变量更快。变量在作用域链中的位置越深,访问所需时间就越长。由于全局变量总处在作用域链的最末端,因此访问速度也是最慢的。
  3. 避免使用width语句,因为它会改变运行上下文作用域链。同样,try-catch语句中的catch子句也有同样的影响,因此也要小心使用。
  4. 嵌套的对象成员会明显影响性能,尽量少用。
  5. 属性或方法在原型链中的位置越深,访问它的速度也越慢。
  6. 通常来说,你可以通过把常量的对象成员、数组元素、跨域变量保存在局部变量中来改善JavaScript性能,因为局部变量访问速度更快。

通过以上策略,你可以极大提高那些需要使用大量JavaScript的Web应用的实际性能。

阅读全文…

php函数良好注释写法

2011年11月22日 汪小俊 没有评论

以前写php函数的没有在乎太多的注释,现在看起来就有点吃力了,更何况要给队友看,相信队友一定会发狂的!

现在讲标准的PHP函数注释写法分享给大家,当然,这是很全的,实际操作中不需要写这么多,觉得必要的写上就可以了

废话不多说,直接上源码!

/**
* @name 名字
* @abstract 申明变量/类/方法
* @access 指明这个变量、类、函数/方法的存取权限
* @author 函数作者的名字和邮箱地址

* @category 组织packages
* @copyright 指明版权信息
* @const 指明常量
* @deprecate 指明不推荐或者是废弃的信息
* @example 示例
* @exclude 指明当前的注释将不进行分析,不出现在文挡中
* @final 指明这是一个最终的类、方法、属性,禁止派生、修改。
* @global 指明在此函数中引用的全局变量
* @include 指明包含的文件的信息
* @link 定义在线连接
* @module 定义归属的模块信息
* @modulegroup 定义归属的模块组
* @package 定义归属的包的信息
* @param 定义函数或者方法的参数信息
* @return 定义函数或者方法的返回信息
* @see 定义需要参考的函数、变量,并加入相应的超级连接。
* @since 指明该api函数或者方法是从哪个版本开始引入的
* @static 指明变量、类、函数是静态的。
* @throws 指明此函数可能抛出的错误异常,极其发生的情况
* @todo 指明应该改进或没有实现的地方
* @var 定义说明变量/属性。
* @version 定义版本信息
*/

 

分类: PHP|MySQL 标签: , ,

短链接之62进制法(php)

2011年11月22日 汪小俊 没有评论

转自:PHPChina

这应该是主流的短链接生成方法了

短网址使用流程:

  • 提交网址存储后获取其编号 如:123456
  • 用dec2Any将编号转换为62进制,并拼接网址 如:http://go.to/w7e
  • 用户访问到 http://go.to/w7e 时,提取短网址后缀 w7e
  • 用any2Dec将短网址后缀转换为10进制,得到链接编号 如:123456
  • 使用编号查询链接,并进行跳转

下面是进制转换所需要的源码:

/**
 * 返回一字符串,十进制 number 以 radix 进制的表示。
 * @param dec       需要转换的数字
 * @param toRadix    输出进制。当不在转换范围内时,此参数会被设定为 2,以便及时发现。
 * @return    指定输出进制的数字
 */
function dec2Any($dec, $toRadix) {
    $MIN_RADIX = 2;
    $MAX_RADIX = 62;
    $num62 = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    if ($toRadix < $MIN_RADIX || $toRadix > $MAX_RADIX) {
        $toRadix = 2;
    }
    if ($toRadix == 10) {
        return $dec;
    }
    // -Long.MIN_VALUE 转换为 2 进制时长度为65
    $buf = array();
    $charPos = 64;
    $isNegative = $dec < 0; //(bccomp($dec, 0) < 0);
    if (!$isNegative) {
        $dec = -$dec; // bcsub(0, $dec);
    }
 
    while (bccomp($dec, -$toRadix) <= 0) {
        $buf[$charPos--] = $num62[-bcmod($dec, $toRadix)];
        $dec = bcdiv($dec, $toRadix);
    }
    $buf[$charPos] = $num62[-$dec];
    if ($isNegative) {
        $buf[--$charPos] = '-';
    }
    $_any = '';
    for ($i = $charPos; $i < 65; $i++) {
        $_any .= $buf[$i];
    }
    return $_any;
}
 
/**
 * 返回一字符串,包含 number 以 10 进制的表示。
 * fromBase 只能在 2 和 62 之间(包括 2 和 62)。
 * @param number    输入数字
 * @param fromRadix    输入进制
 * @return  十进制数字
 */
function any2Dec($number, $fromRadix) {
    $num62 = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $dec = 0;
    $digitValue = 0;
    $len = strlen($number) - 1;
    for ($t = 0; $t <= $len; $t++) {
        $digitValue = strpos($num62, $number[$t]);
        $dec = bcadd(bcmul($dec, $fromRadix), $digitValue);
    }
    return $dec;
}
 
$sol = '<br/>' . PHP_EOL;
echo any2Dec('ZZZZZZ', 62), $sol; // 56800235583
echo dec2Any('123456', 62), $sol; // w7e
echo any2Dec('w7e', 62), $sol; // 123456

如果大家还有什么好的点子也欢迎和我交流~

pixel 短链接之62进制法(php)