Archive for the ‘未分类’ Category

ASP.NET中动态控制RDLC报表

星期二, 06月 3rd, 2008

  在asp.net程序中,可以选择使用水晶报表,功能确实强大.但是web版de水晶报表好像存在版权de问题.如果所作报表不是复杂de一塌糊涂de话,可以使用微软自带deRdlc报表.
  Rdlc优点:
  1:Rdlc报表设计简单
  2:结果存成xml,易于控制
  3:导出格式作de很不错
  这里所说de动态控制报表所指de是:在一些时候,制作了报表之后希望在运行中可以动态de做一些小修改,比如说列de位置,用户控制显示那些列等等.
  控制方法,尝试了这么几种:
  1:控制微软提供de报表对象de属性;
  2:报表全部自动生成
  3:修改报表源文件,然后加载.
  控制微软提供de报表对象de属性:基于这个功能需求,一开始我想到de方法是通过控制微软提供de这些报表对象de属性来实现.因为这种方法最人道了.但是事与愿违,微软deReportViewer对象是用来显示Reportde,自然不行;我使用dereport是自己设计de,localReport,找到Report对象,里面方法有这个几个:report.GetDefaultPageSettings();report.GetDocumentMap()等,第一个是获取打印纸张德设置,第二个是获取doc文档(但是始终出错),都是只读属性;所以,第一种尝试失败.
  第二种方法就是报表全部自动生成.可以找到一个完整de例子,在这里:http://www.gotreportviewer.com/DynamicTable.zip
这个例子里面,他把xml结构derdlc报表写成一个类ReportDefinition,然后通过自定义这个类de内容来得到一个报表.其实际还是为了自己构造一个报表对象dexml.这是加载自定义报表de过程:win下de相关代码 this.reportViewer1.Reset();
this.reportViewer1.LocalReport.LoadReportDefinition(m_rdl);
this.reportViewer1.LocalReport.DataSources.Add(new ReportDataSource(”MyData”, m_dataSet.Tables[0]));
this.reportViewer1.RefreshReport();这是自动生成xmlde相关代码:
private MemoryStream GenerateRdl(List<string> allFields, List<string> selectedFields)
{
 MemoryStream ms = new MemoryStream();
 RdlGenerator gen = new RdlGenerator();
 gen.AllFields = allFields;
 gen.SelectedFields = selectedFields;
 gen.WriteXml(ms);
 ms.Position = 0;
 return ms;
}
  这是完全ReportDefinitionde一部分定义:
namespace Rdl {
 using System.Xml.Serialization;
 /**//// <remarks/>
 [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
 [System.SerializableAttribute()]
 [System.Diagnostics.DebuggerStepThroughAttribute()]
 [System.ComponentModel.DesignerCategoryAttribute("code")]
 [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
 [System.Xml.Serialization.XmlRootAttribute(Namespace=_
  "http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition", IsNullable=false)]
 public partial class Report {
  private object[] itemsField;
  但是几经考虑之后,这个方案也不让人满意,原因是:所有de报表对象都得自己生成,一下子回到了解放前,没有可视化工具de设计既繁琐又复杂.特别是如果设计几个line,然后再来上几个分组de话,工作量巨大.
  于是乎尝试第三种方法:ReportVivwer加载报表前在内存中修改报表源文件.这个方法比较狠,其实可以解决很多问题,包括设计自定义de打印纸张等(这里有另外一种设置打印纸张de方法http://waxdoll.cnblogs.com/archive/2006/03/03/342435.html).
  设计思路是:首先加载rdlc文件到一个XmlDocument对象;然后修改xml内容;把xml序列化成字节流,交给ReportViewer显示.
  这是这一段相关代码:
public Mem

修改了一个很不错的验证码,共享之。

星期一, 06月 2nd, 2008

很早前在PHP喜悦国际村看到de一个验证码类,写de很强.但有些逻辑方面感觉处理de不好,然后我不喜欢完全用session来处理验证码.这在大型系统中是很不好de.
修改后如下.


<?php
/**
* 这个类用于生成验证码图像, 同时可以对用户输入de验证码进行验证
*
* @author ♂bingo↗ [coolhpy@163.com]
* @since 2006-6-17
* @modify feifengxlq <feifengxlq@gmail.com> http://www.phpobject.net/blog
* @modify 2006-11-9
* 修改说明
*/

class authcode
{
/**
* 验证码
* char: 字符
* angle: 字符偏移de角度 (-30 <= angle <= 30)
* color: 字符颜色
*
* @var array
* @access private
*/
var $code = array();
/**
* 字体信息
* space: 字符间隔 (px)
* size: 字体大小 (px)
* left: 第一个字符距离图像最左边de象素 (px)
* top: 字符距离图像最上边de象素 (px)
* file: 字体文件de路径
*
* @var array
* @access private
*/
var $font = array();
/**
* 图像信息
* type: 图像类型
* mime: MIME 类型
* width: 图像de宽 (px)
* height: 图像高 (px)
* func: 创建图像de方法
*
* @var array
* @access private
*/
var $image = array();
/**
* 干扰信息
* type: 干扰类型 (false 表示不使用)
* density: 干扰密度
*
* @var array
* @access private
*/
var $molestation = array();
/**
* 背景色 (RGB)
* r: 红色 (0 - 255)
* g: 绿色 (0 - 255)
* b: 蓝色 (0 - 255)
*
* @var array
* @access private
*/
var $bg_color = array();
/**
* 默认前景色 (RGB)
* r: 红色 (0 - 255)
* g: 绿色 (0 - 255)
* b: 蓝色 (0 - 255)
*
* @var array
* @access private
*/
var $fg_color = array();
var
$authcode=;
/**
* 构造函数,初始化各变量
*
* @access public
*/
function __construct()
{
$this->setCode();
$this->setMolestation();
$this->setImage();
$this->setFont();
$this->setBgColor();
}
/**
* 获取产生deauthcode
*/
function getcode()
{
return
$this->authcode;
}
/**
* 绘制图像
*
* @access public
* @param string 文件名, 留空表示输出到浏览器
* @return void
*/
function paint($filename=)
{
// 创建图像
$im = imagecreatetruecolor($this->image['width'],
$this->image['height']);
// 设置图像背景
$bg_color = imagecolorallocate($im, $this->bg_color['r'],
$this->bg_color['g'],
$this->bg_color['b']);
imagefilledrectangle($im, 0, 0, $this->image['width'],
$this->image['height'], $bg_color);
// 生成验证码相关信息
$code = $this->generateCode();
// 向图像中写入字符
$num = count($code);
$current_left = $this->font['left'];
$current_top = $this->font['top'];
for (
$i=0; $i<$num; $i )
{
$font_color = imagecolorallocate($im, $code[$i]['color']['r'],$code[$i]['color']['g'],$code[$i]['color']['b']);
imagettftext($im, $this->font['size'], $code[$i]['angle'],
$current_left, $current_top, $font_color,
$this->font['file'], $code[$i]['char']);
$current_left = $this->font['size'] $this->font['space'];
$the_code .= $code[$i]['char'];
}
$this->authcode=$the_code;//保存authcode
// 绘制图像干扰
$this->paintMolestation($im);
// 输出
if (isset($filename) && $filename!=)
{
$this->image['func']($im, $filename.$this->image['type']);
} else
{
header(“Cache-Control: no-cache, must-revalidate”);
header(“Content-type: “.$this->image['mime']);
$this->image['func']($im);
}
imagedestroy($im);
}
/**
* 生成随机验证码
*
* @access private
* @return array 生成de验证码
*/
function generateCode()
{
// 创建允许de字符串
$characters = explode(‘,’, $this->code['characters']);
$num = count($characters);
for (
$i=0; $i<$num; $i )
{
if (
substr_count($characters[$i], ‘-’) > 0)
{
$character_range = explode(‘-’, $characters[$i]);
for (
$j=ord($character_range[0]); $j<=ord($character_range[1]);
$j )
{
$array_allow[] = chr($j);
}
}
else
{
$array_allow[] = $array_allow[$i];
}
}
$index = 0;
while (list(
$key, $val) = each($array_allow))
{
$array_allow_tmp[$index] = $val;
$index ;
}
$array_allow = $array_allow_tmp;
// 生成随机字符串
mt_srand((double)microtime() * 1000000);
$code = array();
$index = 0;
$i = 0;
while (
$i < $this->code['length'])
{
$index = mt_rand(0, count($array_allow) - 1);
$code[$i]['char'] = $array_allow[$index];
if (
$this->code['deflect'])
{
$code[$i]['angle'] = mt_rand(-30, 30);
} else
{
$code[$i]['angle'] = 0;
}
if (
$this->code['multicolor'])
{
$code[$i]['color']['r'] = mt_rand(0, 255);
$code[$i]['color']['g'] = mt_rand(0, 255);
$code[$i]['color']['b'] = mt_rand(0, 255);
} else
{
$code[$i]['color']['r'] = $this->fg_color['r'];
$code[$i]['color']['g'] = $this->fg_color['g'];
$code[$i]['color']['b'] = $this->fg_color['b'];
}
$i ;
}
return
$code;
}
/**
* 获取图像类型
*
* @access private
* @param string 扩展名
* @return [mixed] 错误时返回 false
*/
function getImageType($extension)
{
switch (
strtolower($extension))
{
case
‘png’:
$information['mime'] = image_type_to_mime_type(IMAGETYPE_PNG);
$information['func'] = ‘imagepng’;
break;
case
‘gif’:
$information['mime'] = image_type_to_mime_type(IMAGETYPE_GIF);
$information['func'] = ‘imagegif’;
break;
case
‘wbmp’:
$information['mime'] = image_type_to_mime_type(IMAGETYPE_WBMP);
$information['func'] = ‘imagewbmp’;
break;
case
‘jpg’:
$information['mime'] = image_type_to_mime_type(IMAGETYPE_JPEG);
$information['func'] = ‘imagejpeg’;
break;
case
‘jpeg’:
$information['mime'] = image_type_to_mime_type(IMAGETYPE_JPEG);
$information['func'] = ‘imagejpeg’;
break;
case
‘jpe’:
$information['mime'] = image_type_to_mime_type(IMAGETYPE_JPEG);
$information['func'] = ‘imagejpeg’;
break;
default:
$information = false;
}
return
$information;
}
/**
* 绘制图像干扰
*
* @access private
* @param resource 图像资源
* @return void
*/
function paintMolestation(&$im)
{
// 总象素
$num_of_pels = ceil($this->image['width']*$this->image['height']/5);
switch (
$this->molestation['density'])
{
case
‘fewness’:
$density = ceil($num_of_pels / 3);
break;
case
‘muchness’:
$density = ceil($num_of_pels / 3 * 2);
break;
case
‘normal’:
$density = ceil($num_of_pels / 2);
default:
}
switch (
$this->molestation['type'])
{
case
‘point’:
$this->paintPoints($im, $density);
break;
case
‘line’:
$density = ceil($density / 30);
$this->paintLines($im, $density);
break;
case
‘both’:
$density = ceil($density / 2);
$this->paintPoints($im, $density);
$density = ceil($density / 30);
$this->paintLines($im, $density);
break;
default:
break;
}
}
/**
* 画点
*
* @access private
* @param resource 图像资源
* @param int 图像资源
* @return void
*/
function paintPoints(&$im, $quantity)
{
mt_srand((double)microtime()*1000000);
for (
$i=0; $i<$quantity; $i )
{
$randcolor = imagecolorallocate($im, mt_rand(0,255),
mt_rand(0,255), mt_rand(0,255));
imagesetpixel($im, mt_rand(0, $this->image['width']),
mt_rand(0, $this->image['height']), $randcolor);
}
}
/**
* 画线
*
* @access private
* @param resource 图像资源
* @param int 图像资源
* @return void
*/
function paintLines(&$im, $quantity)
{
mt_srand((double)microtime()*1000000);
for (
$i=0; $i<$quantity; $i )
{
$randcolor = imagecolorallocate($im, mt_rand(0,255),
mt_rand(0,255), mt_rand(0,255));
imageline($im, mt_rand(0, $this->image['width']),
mt_rand(0, $this->image['height']),
mt_rand(0, $this->image['width']),
mt_rand(0, $this->image['height']), $randcolor);
}
}
/**
* 设置前景色
*
* @access private
* @param array RGB 颜色
* @return void
*/
function setFgColor($color)
{
if (
is_array($color) && is_integer($color['r']) &&
is_integer($color['g']) && is_integer($color['b']) &&
(
$color['r'] >= 0 && $color['r'] <= 255) &&
(
$color['g'] >= 0 && $color['g'] <= 255) &&
(
$color['b'] >= 0 && $color['b'] <= 255))
{
$this->fg_color = $color;
} else
{
$this->fg_color = array(‘r’=>0,‘g’=>0,‘b’=>0);
}
}
/**
* 设置验证码
*
* @access public
* @param array 字符信息
* characters string 允许de字符
* length int 验证码长度
* deflect boolean 字符是否偏转
* multicolor boolean 字符是否彩色
* @return void
*/
function setCode($code=)
{
if (
is_array($code))
{
if (!isset(
$code[‘c

JavaScript对象模型-执行模型

星期一, 06月 2nd, 2008

简单数值类型: 有Undefined, Null, Boolean, Number和String.注意,描述中de英文单词在这里仅指数据类型de名称,并不特指JSde全局对象N an, Boolean, Number, String等,它们在概念上de区别是比较大de.
对象: 一个无序属性de集合,这些属性de值为简单数值类型、对象或者函数.同上,这里de对象并不特指全局对象Object.
函数: 函数是对象de一种,实现上内部属性[[Class]]值为”Function”,表明它是函数类型,除了对象de内部属性方法外,还有 [[Construct]]、[[Call]]、[[Scope]]等内部属性.函数作为函数调用与构造器(使用new关键字创建实例对象)de处理机制不 一样(Function对象除外),内部方法[[Construct]]用于实现作为构造器de逻辑,方法[[Call]]实现作为函数调用de逻辑.同上, 这里de函数并不特指全局对象Function.
函数在JS这个Prototype语言中可以看作是面向对象语言de类,可以用它来构造对象实例.既然函数可以看作是类,所以每一个函数可以看作是一种扩展数据类型.
内置数据类型(内置对象)
Function: 函数类型de用户接口.
Object: 对象类型de用户接口.
Boolean, Number, String: 分别为这三种简单数值类型de对象包装器,对象包装在概念上有点类似C#中deBox/Unbox.
Date, Array, RegExp: 可以把它们看作是几种内置de扩展数据类型.
首先,Function, Object, Boolean, Number, String, Date, Array, RegExp等都是JavaScript语言de内置对象,它们都可以看作是函数de派生类型,例如Number instanceof Function为true,Number instanceof Object为true.在这个意义上,可以将它们跟用户定义de函数等同看待.
其次,它们各自可以代表一种数据类型,由JS引擎用native code或内置deJS相关代码实现,是暴露给开发者对这些内置数据类型进行操作de接口.在这个意义上,它们都是一种抽象de概念,后面隐藏了具体de实现机制.
在每一个提到Number, Function等单词de地方,应该迅速de在思维中将它们实例化为上面de两种情况之一.
数据类型实现模型描述

Build-in *** data structure: 指JS内部用于实现***类型de数据结构,这些结构我基本上无法直接操作.
Build-in *** object: 指JS内置deNumber, String, Boolean等这些对象,这是JS将内部实现de数据类型暴露给开发者使用de接口.
Build-in *** constructor: 指JS内置de一些构造器,用来构造相应类型de对象实例.它们被包装成函数对象暴露出来,例如我可以使用下面de方法访问到这些函数对象:

Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/

//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4
//
access the build-in number constructor
var number = new Number(123);
var numConstructor1 = number.constructor; //or
var numConstructor2 = new Object(123).constructor;
//both numConstructor1 and numConstructor2 are the build-in Number constructor
numConstructor1 == numConstructor2 //result: true
//
access the build-in object constructor
var objConstructor1 = {}.constructor; //or
var objConstructor2 = new Object().constructor;
//both objConstructor1 and objConstructor2 are the build-in Object constructor
objConstructor1==objConstructor2 //result: true
具体实现上,上图中横向之间可能也存在关联,例如对于build-in data structure和constructor,Function、 Date、 Array、 RegExp等都可以继承Objectde结构而实现,但这是具体实现相关de事情了.
关于简单数值类型de对象化
这是一个细微de地方,下面描述对于Boolean, String和Number这三种简单数值类型都适用,以Number为例说明.
JS规范要求: 使用var num1=123;这样de相关代码,直接返回基本数据类型,就是说返回de对象不是派生自Number和Object类型,用num1 instanceof Object测试为false;使用new关键字创建则返回Number类型,例如var num2=new Number(123); num2 instanceof Number为true.
将Number当作函数调用,返回结果会转换成简单数值类型.下面是测试相关代码:

Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/

//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4
var num1 = new Number(123); //num1 derived from Number & Object
num1 instanceof Number //result: true
num1 instanceof Object //result: true
//convert the num1 from Number type to primitive type, so it’s no longer an instance of Number or Object
num1 = Number(num1);
num1 instanceof Number //result: false
num1 instanceof Object //result: false
var num2 = 123; //num2 is a primitive type
num2 instanceof Number //result: false
num2 instanceof Object //result: false虽然我得到了一个简单数值类型,但它看起来仍然是一个JS Object对象,具有Object以及相应类型de所有属性和方法,使用上基本没有差别,唯一不同之处是instanceofde测试结果.
Prototype继承
Prototype

每个对象都有一个[[Prototype]]de内部属性,它de值为null或者另外一个对象.函数对象都有一个显示deprototype属性,它并不是内 部[[Prototype]]属性.不同deJS引擎实现者可以将内部[[Prototype]]属性命名为任何名字,并且设置它de可见性,只在JS引擎内 部使用.虽然无法在JS相关代码中访问到内部[[Prototype]](FireFox中可以,名字为__proto__因为Mozilla将它公开了), 但可以使用对象deisPrototypeOf()方法进行测试,注意这个方法会在整个Prototype链上进行判断.
使用obj.propName访问一个对象de属性时,按照下面de步骤进行处理(假设objde内部[[Prototype]]属性名为__proto__):
1. 如果obj存在propName属性,返回属性de值,否则
2. 如果obj.__proto__为null,返回undefined,否则
3. 返回obj.__proto__.propName
调用对象de方法跟访问属性搜索过程一样,因为方法de函数对象就是对象de一个属性值.
提示: 上面步骤中隐含了一个递归过程,步骤3中obj.__proto__是另外一个对象,同样将采用1, 2, 3这样de步骤来搜索propName属性.
例如下图所示,object1将具备属性prop1, prop2, prop3以及方法fn1, fn2, fn3.图中虚线箭头表示prototype链.

这就是基于Prototypede继承和共享.其中object1de方法fn2来自object2,概念上即object2重写了object3de方法fn2.
JavaScript对象应当都通过prototype链关联起来,最顶层是Object,即对象都派生自Object类型.
类似C 等面向对象语言用类(被抽象了de类型)来承载方法,用对象(实例化对象)承载属性,Prototype语言只用实例化de对象来承载方法和属性.本质区别是前者基于内存结构de描述来实现继承,后者基于具体de内存块实现.
对象创建过程
JS中只有函数对象具备类de概念,因此要创建一个对象,必须使用函数对象.函数对象内部有[[Construct]]方法和[[Call]]方法, [[Construct]]用于构造对象,[[Call]]用于函数调用,只有使用new操作符时才触发[[Construct]]逻辑.
var obj=new Object(); 是使用内置deObject这个函数对象创建实例化对象obj.var obj={};和var obj=[];这种相关代码将由JS引擎触发Object和Arrayde构造过程.function fn(){}; var myObj=new fn();是使用用户定义de类型创建实例化对象.
new Fn(args)de创建过程如下(即函数对象de[[Construct]]方法处理逻辑,对象de创建过程).另外函数对象本身de创建过程(指定义函数或者用Function创建一个函数对象等方式)虽然也使用了下面de处理逻辑,但有特殊de地方,后面再描述.
1. 创建一个build-in object对象obj并初始化
2. 如果Fn.prototype是Object类型,则将objde内部[[Prototype]]设置为Fn.prototype,否则objde[[Prototype]]将为其初始化值(即Object.prototype)
3. 将obj作为this,使用args参数调用Fnde内部[[Call]]方法
3.1 内部[[Call]]方法创建当前执行上下文
3.2 调用Fde函数体
3.3 销毁当前de执行上下文
3.4 返回F函数体de返回值,如果Fde函数体没有返回值则返回undefined
4. 如果[[Call]]de返回值是Object类型,则返回这个值,否则返回obj
注意步骤2中, prototype指对象显示deprototype属性,而[[Prototype]]则代表对象内部Prototype属性(隐式de).
构成对象Prototype链de是内部隐式de[[Prototype]],而并非对象显示deprototype属性.显示deprototype只有在函数 对象上才有意义,从上面de创建过程可以看到,函数deprototype被赋给派生对象隐式[[Prototype]]属性,这样根据Prototype规 则,派生对象和函数deprototype对象之间才存在属性、方法de继承/共享关系.
用相关代码来做一些验证:

Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/

//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4
function fn(){}
//the value of implicit [[Prototype]] property of those objects derived from fn will be assigned to fn.prototype
fn.prototype={ attr1:aaa, attr2:bbb};
var obj=new fn();
document.write(obj.attr1
<br />); //result: aaa
document.write(obj.attr2 <br />); //result: bbb
document.write(obj instanceof fn); //result: true
document.write(<br />);
//I change the prototype of fn here, so by the algorithm of Prototype the obj is no longer the instance of fn,
//
but this won’t affect the obj and its [[Prototype]] property, and the obj still has attr1 and attr2 properties
fn.prototype={};
document.write(obj.attr1
<br />); //result: aaa
document.write(obj.attr2 <br />); //result: bbb
document.write(obj instanceof fn); //result: false关于创建过程返回值de验证:

Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/

//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4
function fn(){
//according to step 4 described above,
//the new fn() operation will return the object { attr1: 111, attr2: 222 }, it’s not an instance of fn!
return { attr1: 111, attr2: 222 };
}
fn.prototype
={ attr1:aaa, attr2:bbb};
var obj=new fn();
document.write(obj.attr1
<br />); //result: 111
document.write(obj.attr2 <br />); //result: 222
document.write(obj instanceof fn); //result: false
做个练习
经过上面de理解应,请写出下面这幅图de实现相关代码.图中CF是一个函数,Cfp是CFdeprototype对象,cf1, cf2, cf3, cf4, cf5都是CFde实例对象.虚线箭头表示隐式Prototype关系,实线箭头表示显示prototype关系.

供参考de实现方案:

Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/

//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4
function CF(q1, q2){
this.q1=q1;
this.q2=q2;
}
CF.P1
=“P1 in CF”;
CF.P2
=“P2 in CF”;
function Cfp(){
this.CFP1=CFP1 in Cfp;
}
CF.prototype
=new Cfp();
var cf1=new CF(aaa, bbb);
document.write(cf1.CFP1
<br />); //result: CFP1 in Cfp
document.write(cf1.q1 <br />); //result: aaa
document.write(cf1.q2 <br />); //result: bbb
本地属性与继承属性
对象通过隐式Prototype链能够实现属性和方法de继承,但prototype也是一个普通对象,就是说它是一个普通de实例化de对象,而不是纯粹抽象de数据结构描述.所以就有了这个本地属性与继承属性de问题.
首先看一下设置对象属性时de处理过程.JS定义了一组attribute,用来描述对象de属性property,以表明属性property是否可以在JavaScript相关代码中设值、被for in枚举等.
obj.propName=valuede赋值语句处理步骤如下:
1. 如果propNamedeattribute设置为不能设值,则返回
2. 如果obj.propName不存在,则为obj创建一个属性,名称为propName
3. 将obj.propNamede值设为value
可以看到,设值过程并不会考虑Prototype链,道理很明显,objde内部[[Prototype]]是一个实例化de对象,它不仅仅向obj共享属性,还可能向其它对象共享属性,修改它可能影响其它对象.
用上面CF, Cfpde示例来说明,实例对象cf1具有本地属性q1, q2以及继承属性CFP1,如果执行cf1.CFP1=”",那么cf1就具有本地属性CFP1了,测试结果如下:

Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/

//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4
var cf1=new CF(aaa, bbb);
var cf2=new CF(111, 222);
document.write(cf1.CFP1
<br />); //result: CFP1 in Cfp
document.write(cf2.CFP1 <br />); //result: CFP1 in Cfp
//it will result in a local property in cf1
cf1.CFP1=new value for cf1;
//changes on CF.prototype.CFP1 will affect cf2 but not cf1, because there’s already a local property with
//the name CFP1 in cf1, but no such one in cf2
CF.prototype.CFP1=new value for Cfp;
document.write(cf1.CFP1
<br />); //result: new value for cf1
document.write(cf2.CFP1 <br />); //result: new value for Cfp
语义上de混乱?
还是使用上面CF, Cfp示例de场景.
根据Prototypede机制,我可以说对象cf1, cf2等都继承了对象Cfpde属性和方法,所以应该说他们之间存在继承关系.属性de继承/共享是沿着隐式Prototype链作用de,所以继承关系也应当理解为沿着这个链.
我再看instanceOf操作,只有cf1 instanceOf CF才成立,我说cf1是CFde实例对象,CF充当了类de角色,而不会说cf1是Cfpde实例对象,这样我应当说cf1继承自CF? 但CF充当de只是一个第三方工厂de角色,它跟cf1之间并没有属性继承这个关系.
把CF, Cfp看作一个整体来理解也同样牵强.
Prototype就是Prototype,没有必要强把JavaScript与面向对象概念结合起来, JavaScript只具备有限de面向对象能力,从另外de角度我可以把它看成函数语言、动态语言,所以它是吸收了多种语言特性de精简版.
对象模型
Where are we?
1. 了解了JavaScriptde数据类型,清楚了象Number这样de系统内置对象具有多重身份: a)它们本身是一个函数对象,只是由引擎内部实现而已,b)它们代表一种数据类型,我可以用它们定义、操作相应类型de数据,c)在它们背后隐藏了引擎de 内部实现机制,例如内部de数据结构、各种被包装成了JavaScript对象de构造器等.
2. 了解了Prototype机制,知道对象是如何通过它们继承属性和方法,知道了在创建对象过程中JS引擎内部是如何设置Prototype关系de.
接下来对用户自定义函数对象本身de创建过程进行了解之后,我就可以对JavaScriptde对象模型来一个整体性deoverview了.
函数对象创建过程
JavaScript相关代码中定义函数,或者调用Function创建函数时,最终都会以类似这样de形式调用Function函数:var newFun=Function(funArgs, funBody); .创建函数对象de主要步骤如下:
1. 创建一个build-in object对象fn
2. 将fnde内部[[Prototype]]设为Function.prototype
3. 设置内部de[[Call]]属性,它是内部实现de一个方法,处理逻辑参考对象创建过程de步骤3
4. 设置内部de[[Construct]]属性,它是内部实现de一个方法,处理逻辑参考对象创建过程de步骤1,2,3,4
5. 设置fn.length为funArgs.length,如果函数没有参数,则将fn.length设置为0
6. 使用new Object()同样de逻辑创建一个Object对象fnProto
7. 将fnProto.constructor设为fn
8. 将fn.prototype设为fnProto
9. 返回fn
步骤1跟步骤6de区别为,步骤1只是创建内部用来实现Object对象de数据结构(build-in object structure),并完成内部必要de初始化工作,但它de[[Prototype]]、[[Call]]、[[Construct]]等属性应当为 null或者内部初始化值,即我可以理解为不指向任何对象(对[[Prototype]]这样de属性而言),或者不包含任何处理(对[[Call]]、 [[Construct]]这样de方法而言).步骤6则将按照前面描述de对象创建过程创建一个新de对象,它de[[Prototype]]等被设置了.
从上面de处理步骤可以了解,任何时候我定义一个函数,它deprototype是一个Object实例,这样默认情况下我创建自定义函数de实例对象时,它们dePrototype链将指向Object.prototype.
另外,Function一个特殊de地方,是它de[[Call]]和[[Construct]]处理逻辑一样.
JavaScript对象模型

红色虚线表示隐式Prototype链.
这张对象模型图中包含了太多东西,不少地方需要仔细体会,可以写些测试相关代码进行验证.彻底理解了这张图,对JavaScript语言de了解也就差不多了.下面是一些补充说明:
1. 图中有好几个地方提到build-in Function constructor,这是同一个对象,可以测试验证:

Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/

//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4
Function==Function.constructor //result: true
Function==Function.prototype.constructor //result: true
Function==Object.constructor //result: true
//
Function also equals to Number.constructor, String.constructor, Array.constructor, RegExp.constructor, etc.
function fn(){}
Function
==fn.constructor //result: true这说明了几个问题: Function指向系统内置de函数构造器(build-in Function constructor);Function具有自举性;系统中所有函数都是由Function构造.
2. 左下角deobj1, obj2…objn范指用类似这样de相关代码创建de对象: function fn1(){}; var obj1=new fn1();
这些对象没有本地constructor方法,但它们将从Prototype链上得到一个继承deconstructor方法,即fn.prototype.constructor,从函数对象de构造过程可以知道,它就是fn本身了.
右下角deobj1, obj2…objn范指用类似这样de相关代码创建de对象: var obj1=new Object();或var obj1={};或var obj1=new Number(123);或obj1=/\w /;等等.所以这些对象Prototype链de指向、从Prototype链继承而来de constructorde值(指它们deconstructor是build-in Number constructor还是build-in Object constructor等)等依赖于具体de对象类型.另外注意de是,var obj=new Object(123);这样创建de对象,它de类型仍然是Number,即同样需要根据参数值de类型来确定.
同样它们也没有本地constructor,而是从Prototype链上获得继承deconstructor方法,即build-in *** constructor,具体是哪一个由数据类型确定.
3. 关于图中Prototype链de补充说明:
Object.prototype是整个链de终结点,它de内部[[Prototype]]为null.
所有函数dePrototype链都指向Function.prototype.
FunctiondePrototype链指向Function.prototype,这是规范要求de,因为设计者将Function设计为具有自举性. FunctiondePrototype链这样设计之后,Function.constructor==Function, Function instanceOf Function都为true.另外Function已经是最顶层de构造器,但Function本身也是一个函数对象,它必然是由某个东西创建出来de,这 样自举在语义上合情合理.
Function.prototypedePrototype链指向Object.prototype,这也是规范强制要求de.首先 Function.prototype是Functionde一个实例对象(typeof Function.prototype可以知道它是一个Function,instanceOf无法通过测试,因为Prototype链在内部被额外设置 了),所以按照Prototypede规则,Function.prototypede内部[[Prototype]]值应当为 Function.prototype这个对象,即它dePrototype链指向自己本身.这样一方面在Prototype链上造成一个死循环,另一方面 它本身成为了一个终结点,结果就是所有函数对象将不是派生自Object了.加上这个强制要求之后,Prototype链只有唯一de一个终结点.
4. 因为Function.prototype是一个函数对象,所以它应当具有显示deprototype属性,即 Function.prototype.prototype,但只有FireFox中可以访问到,IE、Opera、Safari都无法访问.所以图中用 了个表示不存在de符号.
5. 用户自定义函数(user defined functions)默认情况下[[Prototype]]值是Object.prototype,即它de隐式Prototype链指向 Object.prototype,所以图中就这样表示了,但并不代表总是这样,当用户设置了自定义函数deprototype属性之后,情况就不同了.
执行模型
执行上下文(Execution Context)简介
JavaScript相关代码运行de地方都存在执行上下文,它是一个概念,一种机制,用来完成JavaScript运行时作用域、生存期等方面de处理.执行上 下文包括Variable Object、Variable Instatiation、Scope/Scope Chain等概念,在不同de场景/执行环境下,处理上存在一些差异,下面先对这些场景进行说明.
函数对象分为用户自定义函数对象和系统内置函数对象,对于用户自定义函数对象将按照下面描述de机制进行处理,但内置函数对象与具体实现相关,ECMA规范对它们执行上下文de处理没有要求,即它们基本不适合本节描述de内容.
执行deJavaScript相关代码分三种类型,后面会对这三种类型处理上不同de地方进行说明:
1. Global Code,即全局de、不在任何函数里面de相关代码,例如一个js文件、嵌入在HTML页面中dejs相关代码等.
2. Eval Code,即使用eval()函数动态执行deJS相关代码.
3. Function Code,即用户自定义函数中de函数体JS相关代码.
基本原理
在用户自定义函数中,可以传入参数、在函数中定义局部变量,函数体相关代码可以使用这些入参、局部变量.背后de机制是什么样呢?
当JS执行流进入函数时,JavaScript引擎在内部创建一个对象,叫做Variable Object.对应函数de每一个参数,在Variable Object上添加一个属性,属性de名字、值与参数de名字、值相同.函数中每声明一个变量,也会在Variable Object上添加一个属性,名字就是变量名,因此为变量赋值就是给Variable Object对应de属性赋值.在函数中访问参数或者局部变量时,就是在variable Object上搜索相应de属性,返回其值.
一般情况下Variable Object是一个内部对象,JS相关代码中无法直接访问.规范中对其实现方式也不做要求,因此它可能只是引擎内部de一种数据结构.
大致处理方式就这样,但作用域de概念不只这么简单,例如函数体中可以使用全局变量、函数嵌套定义时情况更复杂点.这些情况下怎样处理? JavaScript引擎将不同执行位置上deVariable Object按照规则构建一个链表,在访问一个变量时,先在链表de第一个Variable Object上查找,如果没有找到则继续在第二个Variable Object上查找,直到搜索结束.这就是Scope/Scope Chainde大致概念.
下面是各个方面详细de处理.
Global Object
JavaScriptde运行环境都必须存在一个唯一de全局对象-Global Object,例如HTML中dewindow对象.Global Object是一个宿主对象,除了作为JavaScript运行时de全局容器应具备de职责外,ECMA规范对它没有额外要求.它包Math、 String、Date、parseInt等JavaScript中内置de全局对象、函数(都作为Global Objectde属性),还可以包含其它宿主环境需要de一些属性.
Variable Object
上面简述了Variable Objectde基本概念.创建Variable Object,将参数、局部变量设置为Variable Object属性de处理过程叫做Variable Instatiation-变量实例化,后面结合Scope Chain再进行详细说明.
Global Code
Variable Object就是Global Object,这是Variable Object唯一特殊de地方(指它是内部de无法访问de对象而言).

Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/

var globalVariable = WWW;
document.write(window.globalVariable);
//result: WWW上面相关代码在Global Code方式下运行,根据对Variable Objectde处理,定义变量globalVariable时就会在Global Object(即window)对象上添加这个属性,所以输出是WWW这个值.
Function Code
Variable Object也叫做Activation Object(因为有一些差异存在,所以规范中重新取一个名字以示区别,Global Code/Eval Code中叫Variable Object,Function Code中就叫做Activation Object).
每次进入函数执行都会创建一个新deActivation Object对象,然后创建一个arguments对象并设置为Activation Objectde属性,再进行Variable Instantiation处理.
在退出函数时,Activation Object会被丢弃(并不是内存释放,只是可以被垃圾回收了).
附arguments对象de属性:
length: 为实际传入参数de个数.注意,参考函数对象创建过程,函数对象上delength为函数定义时要求de参数个数;
callee: 为执行de函数对象本身.目de是使函数对象能够引用自己,例如需要递归调用de地方.
function fnName(…) { … }这样定义函数,它de递归调用可以在函数体内使用fnName完成.var fn=function(…) { … }这样定义匿名函数,在函数体内无法使用名字引用自己,通过arguments.callee就可以引用自己而实现递归调用.
参数列表: 调用者实际传入de参数列表.这个参数列表提供一个使用索引访问实际参数de方法.Variable Instantiation处理时会在Activation Object对象上添加属性,前提是函数声明时有指定参数列表.如果函数声明中不给出参数列表,或者实际调用参数个数与声明时de不一样,可以通过 arguments访问各个参数.
arguments中de参数列表与Activation Object上de参数属性引用de是相同de参数对象(如果修改,在两处都会反映出来).规范并不要求arguments是一个数组对象,下面是一个测试:

Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/

//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4
var argumentsLike = { 0: aaa, 1: 222, 2: WWW, length: 3, callee: function() { } };
document.write(argumentsLike[
2] <br />); //result: WWW
document.write(argumentsLike[1] <br />); //result: 222
//
convert the argumentsLike to an Array object, just as we can do this for the arguments property
var array = [].slice.apply(argumentsLike);
document.write(array
instanceof Array); //result: true
document.write(<br />);
document.write(array.reverse().join(
|)); //result: WWW|222|aaa
Eval Code
Variable Object就是调用eval时当前执行上下文中deVariable Object.在Global Code中调用eval函数,它deVariable Object就是Global Object;在函数中调用eval,它deVariable Object就是函数deActivation Object.

Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/

//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4
function fn(arg){
var innerVar = variable in function;
eval(
\
var evalVar = “variable in eval”; \
document.write(arg “<br />”); \
document.write(innerVar “<br />”); \
);
document.write(evalVar);
}
fn(
arguments for function);输出结果是:
arguments for function
variable in function
variable in eval
说明: eval调用中可以访问函数fnde参数、局部变量;在eval中定义de局部变量在函数fn中也可以访问,因为它们deVarible Object是同一个对象.
Scope/Scope Chain
首先Scope Chain是一个类似链表/堆栈de结构,里面每个元素基本都是Variable Object/Activation Object.
其次存在执行上下文de地方都有当前Scope Chain,可以理解为Scope Chain就是执行上下文de具体表现形式.
Global Code
Scope Chain只包含一个对象,即Global Object.在开始JavaScript相关代码de执行之前,引擎会创建好这个Scope Chain结构.
Function Code
函数对象在内部都有一个[[Scope]]属性,用来记录该函数所处位置deScope Chain.
创建函数对象时,引擎会将当前执行环境deScope Chain传给Functionde[[Construct]]方法.[[Construct]]会创建一个新deScope Chain,内容与传入deScope Chain完全一样,并赋给被创建函数de内部[[Scope]]属性.在前面函数对象创建过程一节中,这个处理位于步骤4和5之间.
进入函数调用时,也会创建一个新deScope Chain,包括同一个函数de递归调用,退出函数时这个Scope Chain被丢弃.新建deScope Chain第一个对象是Activation Object,接下来de内容与内部[[Scope]]上存储deScope Chain内容完全一样.
Eval Code
进入Eval Code执行时会创建一个新deScope Chain,内容与当前执行上下文deScope Chain完全一样.
实例说明
Scope Chainde原理就上面这些,必须结合JS相关代码de执行、Variable Instantiationde细节处理,才能理解上面这些如何产生作用,下面用一个简单de场景来综合说明.假设下面是一段JavaScriptdeGlobal Code:

Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/

var outerVar1=variable in global code;
function fn1(arg1, arg2){
var innerVar1=variable in function code;
function fn2() { return outerVar1 - innerVar1 - - (arg1 arg2); }
return fn2();
}
var outerVar2=fn1(10, 20);执行处理过程大致如下:
1. 初始化Global Object即windo0,0)”>20);

执行处理过程大致如下:
1. 初始化Global Object即window对象,Variable Object为window对象本身.

可以把编码转换成 gb2312编码lib.UTF8toGB2312.js

星期一, 06月 2nd, 2008

//Author: Unknow
//把编码转换成 gb2312编码
function UrlEncode(str)
{
var i, c, ret=”", strSpecial=”!\”#$%&’()* ,/:;<=>?@[\]^`{|}~%”;
for(i = 0; i < str.length; i )
{
//alert(str.charCodeAt(i));
c = str.charAt(i);
if(c==” “)
ret =” “;
else if(strSpecial.indexOf(c)!=-1)
ret = “%” str.charCodeAt(i).toString(16);
if(z[str.charCodeAt(i)] != null)
{
d = z[str.charCodeAt(i)];
try
{
ret = “%” d.slice(0,2) “%” d.slice(-2);
}
catch (e)
{
alert(” $$ error name = ” e.name “, message = ” e.message “, d ” i “= ” str.charCodeAt(i))
}
}
else
ret = c;
}
return ret;
}
function getSpell(str, sp)
{
var i, c, t, ret=”";
if(sp == null)
sp=”";
for(i = 0; i < str.length; i )
{
if(str.charCodeAt(i) >= 0×4e00)
{
c = parseInt(z[str.charCodeAt(i)], 16);
if(c < 55290)
{
for(t = qswhSpell.length-1; t > 0; t = t - 2)
if(qswhSpell[t] <= c)
break;
if(t > 0)
ret = qswhSpell[t - 1] sp;
}
}
}
return ret.substr(0, ret.length-sp.length);
}
var z = new Array();z[0x00A4]=’A1E8′;z[0x00A7]=’A1EC’;z[0x00A8]=’A1A7′;z[0x00B0]=’A1E3′;z[0x00B1]=’A1C0′;z[0x00B7]=’A1A4′;z[0x00D7]=’A1C1′;z[0x00E0]=’A8A4′;z[0x00E1]=’A8A2′;z[0x00E8]=’A8A8′;z[0x00E9]=’A8A6′;z[0x00EA]=’A8BA’;z[0x00EC]=’A8AC’;z[0x00ED]=’A8AA’;z[0x00F2]=’A8B0′;z[0x00F3]=’A8AE’;z[0x00F7]=’A1C2′;z[0x00F9]=’A8B4′;z[0x00FA]=’A8B2′;z[0x00FC]=’A8B9′;z[0x0101]=’A8A1′;z[0x0113]=’A8A5′;z[0x011B]=’A8A7′;z[0x012B]=’A8A9′;z[0x014D]=’A8AD’;z[0x016B]=’A8B1′;z[0x01CE]=’A8A3′;z[0x01D0]=’A8AB’;z[0x01D2]=’A8AF’;z[0x01D4]=’A8B3′;z[0x01D6]=’A8B5′;z[0x01D8]=’A8B6′;z[0x01DA]=’A8B7′;z[0x01DC]=’A8B8′;z[0x02C7]=’A1A6′;z[0x02C9]=’A1A5′;z[0x0391]=’A6A1′;z[0x0392]=’A6A2′;z[0x0393]=’A6A3′;z[0x0394]=’A6A4′;z[0x0395]=’A6A5′;z[0x0396]=’A6A6′;z[0x0397]=’A6A7′;z[0x0398]=’A6A8′;z[0x0399]=’A6A9′;z[0x039A]=’A6AA’;z[0x039B]=’A6AB’;z[0x039C]=’A6AC’;z[0x039D]=’A6AD’;z[0x039E]=’A6AE’;z[0x039F]=’A6AF’;z[0x03A0]=’A6B0′;z[0x03A1]=’A6B1′;z[0x03A3]=’A6B2′;z[0x03A4]=’A6B3′;z[0x03A5]=’A6B4′;z[0x03A6]=’A6B5′;z[0x03A7]=’A6B6′;z[0x03A8]=’A6B7′;z[0x03A9]=’A6B8′;z[0x03B1]=’A6C1′;z[0x03B2]=’A6C2′;z[0x03B3]=’A6C3′;z[0x03B4]=’A6C4′;z[0x03B5]=’A6C5′;z[0x03B6]=’A6C6′;z[0x03B7]=’A6C7′;z[0x03B8]=’A6C8′;z[0x03B9]=’A6C9′;z[0x03BA]=’A6CA’;z[0x03BB]=’A6CB’;z[0x03BC]=’A6CC’;z[0x03BD]=’A6CD’;z[0x03BE]=’A6CE’;z[0x03BF]=’A6CF’;z[0x03C0]=’A6D0′;z[0x03C1]=’A6D1′;z[0x03C3]=’A6D2′;z[0x03C4]=’A6D3′;z[0x03C5]=’A6D4′;z[0x03C6]=’A6D5′;z[0x03C7]=’A6D6′;z[0x03C8]=’A6D7′;z[0x03C9]=’A6D8′;z[0x0401]=’A7A7′;z[0x0410]=’A7A1′;z[0x0411]=’A7A2′;z[0x0412]=’A7A3′;z[0x0413]=’A7A4′;z[0x0414]=’A7A5′;z[0x0415]=’A7A6′;z[0x0416]=’A7A8′;z[0x0417]=’A7A9′;z[0x0418]=’A7AA’;z[0x0419]=’A7AB’;z[0x041A]=’A7AC’;z[0x041B]=’A7AD’;z[0x041C]=’A7AE’;z[0x041D]=’A7AF’;z[0x041E]=’A7B0′;z[0x041F]=’A7B1′;z[0x0420]=’A7B2′;z[0x0421]=’A7B3′;z[0x0422]=’A7B4′;z[0x0423]=’A7B5′;z[0x0424]=’A7B6′;z[0x0425]=’A7B7′;z[0x0426]=’A7B8′;z[0x0427]=’A7B9′;z[0x0428]=’A7BA’;z[0x0429]=’A7BB’;z[0x042A]=’A7BC’;z[0x042B]=’A7BD’;z[0x042C]=’A7BE’;z[0x042D]=’A7BF’;z[0x042E]=’A7C0′;z[0x042F]=’A7C1′;z[0x0430]=’A7D1′;z[0x0431]=’A7D2′;z[0x0432]=’A7D3′;z[0x0433]=’A7D4′;z[0x0434]=’A7D5′;z[0x0435]=’A7D6′;z[0x0436]=’A7D8′;z[0x0437]=’A7D9′;z[0x0438]=’A7DA’;z[0x0439]=’A7DB’;z[0x043A]=’A7DC’;z[0x043B]=’A7DD’;z[0x043C]=’A7DE’;z[0x043D]=’A7DF’;z[0x043E]=’A7E0′;z[0x043F]=’A7E1′;z[0x0440]=’A7E2′;z[0x0441]=’A7E3′;z[0x0442]=’A7E4′;z[0x0443]=’A7E5′;z[0x0444]=’A7E6′;z[0x0445]=’A7E7′;z[0x0446]=’A7E8′;z[0x0447]=’A7E9′;z[0x0448]=’A7EA’;z[0x0449]=’A7EB’;z[0x044A]=’A7EC’;z[0x044B]=’A7ED’;z[0x044C]=’A7EE’;z[0x044D]=’A7EF’;z[0x044E]=’A7F0′;z[0x044F]=’A7F1′;z[0x0451]=’A7D7′;z[0x2014]=’A1AA’;z[0x2016]=’A1AC’;z[0x2018]=’A1AE’;z[0x2019]=’A1AF’;z[0x201C]=’A1B0′;z[0x201D]=’A1B1′;z[0x2026]=’A1AD’;z[0x2030]=’A1EB’;z[0x2032]=’A1E4′;z[0x2033]=’A1E5′;z[0x203B]=’A1F9′;z[0x2103]=’A1E6′;z[0x2116]=’A1ED’;z[0x2160]=’A2F1′;z[0x2161]=’A2F2′;z[0x2162]=’A2F3′;z[0x2163]=’A2F4′;z[0x2164]=’A2F5′;z[0x2165]=’A2F6′;z[0x2166]=’A2F7′;z[0x2167]=’A2F8′;z[0x2168]=’A2F9′;z[0x2169]=’A2FA’;z[0x216A]=’A2FB’;z[0x216B]=’A2FC’;z[0x2190]=’A1FB’;z[0x2191]=’A1FC’;z[0x2192]=’A1FA’;z[0x2193]=’A1FD’;z[0x2208]=’A1CA’;z[0x220F]=’A1C7′;z[0x2211]=’A1C6′;z[0x221A]=’A1CC’;z[0x221D]=’A1D8′;z[0x221E]=’A1DE’;z[0x2220]=’A1CF’;z[0x2225]=’A1CE’;z[0x2227]=’A1C4′;z[0x2228]=’A1C5′;z[0x2229]=’A1C9′;z[0x222A]=’A1C8′;z[0x222B]=’A1D2′;z[0x222E]=’A1D3′;z[0x2234]=’A1E0′;z[0x2235]=’A1DF’;z[0x2236]=’A1C3′;z[0x2237]=’A1CB’;z[0x223D]=’A1D7′;z[0x2248]=’A1D6′;z[0x224C]=’A1D5′;z[0x2260]=’A1D9′;z[0x2261]=’A1D4′;z[0x2264]=’A1DC’;z[0x2265]=’A1DD’;z[0x226E]=’A1DA’;z[0x226F]=’A1DB’;z[0x2299]=’A1D1′;z[0x22A5]=’A1CD’;z[0x2312]=’A1D0′;z[0x2460]=’A2D9′;z[0x2461]=’A2DA’;z[0x2462]=’A2DB’;z[0x2463]=’A2DC’;z[0x2464]=’A2DD’;z[0x2465]=’A2DE’;z[0x2466]=’A2DF’;z[0x2467]=’A2E0′;z[0x2468]=’A2E1′;z[0x2469]=’A2E2′;z[0x2474]=’A2C5′;z[0x2475]=’A2C6′;z[0x2476]=’A2C7′;z[0x2477]=’A2C8′;z[0x2478]=’A2C9′;z[0x2479]=’A2CA’;z[0x247A]=’A2CB’;z[0x247B]=’A2CC’;z[0x247C]=’A2CD’;z[0x247D]=’A2CE’;z[0x247E]=’A2CF’;z[0x247F]=’A2D0′;z[0x2480]=’A2D1′;z[0x2481]=’A2D2′;z[0x2482]=’A2D3′;z[0x2483]=’A2D4′;z[0x2484]=’A2D5′;z[0x2485]=’A2D6′;z[0x2486]=’A2D7′;z[0x2487]=’A2D8′;z[0x2488]=’A2B1′;z[0x2489]=’A2B2′;z[0x248A]=’A2B3′;z[0x248B]=’A2B4′;z[0x248C]=’A2B5′;z[0x248D]=’A2B6′;z[0x248E]=’A2B7′;z[0x248F]=’A2B8′;z[0x2490]=’A2B9′;z[0x2491]=’A2BA’;z[0x2492]=’A2BB’;z[0x2493]=’A2BC’;z[0x2494]=’A2BD’;z[0x2495]=’A2BE’;z[0x2496]=’A2BF’;z[0x2497]=’A2C0′;z[0x2498]=’A2C1′;z[0x2499]=’A2C2′;z[0x249A]=’A2C3′;z[0x249B]=’A2C4′;z[0x2500]=’A9A4′;z[0x2501]=’A9A5′;z[0x2502]=’A9A6′;z[0x2503]=’A9A7′;z[0x2504]=’A9A8′;z[0x2505]=’A9A9′;z[0x2506]=’A9AA’;z[0x2507]=’A9AB’;z[0x2508]=’A9AC’;z[0x2509]=’A9AD’;z[0x250A]=’A9AE’;z[0x250B]=’A9AF’;z[0x250C]=’A9B0′;z[0x250D]=’A9B1′;z[0x250E]=’A9B2′;z[0x250F]=’A9B3′;z[0x2510]=’A9B4′;z[0x2511]=’A9B5′;z[0x2512]=’A9B6′;z[0x2513]=’A9B7′;z[0x2514]=’A9B8′;z[0x2515]=’A9B9′;z[0x2516]=’A9BA’;z[0x2517]=’A9BB’;z[0x2518]=’A9BC’;z[0x2519]=’A9BD’;z[0x251A]=’A9BE’;z[0x251B]=’A9BF’;z[0x251C]=’A9C0′;z[0x251D]=’A9C1′;z[0x251E]=’A9C2′;z[0x251F]=’A9C3′;z[0x2520]=’A9C4′;z[0x2521]=’A9C5′;z[0x2522]=’A9C6′;z[0x2523]=’A9C7′;z[0x2524]=’A9C8′;z[0x2525]=’A9C9′;z[0x2526]=’A9CA’;z[0x2527]=’A9CB’;z[0x2528]=’A9CC’;z[0x2529]=’A9CD’;z[0x252A]=’A9CE’;z[0x252B]=’A9CF’;z[0x252C]=’A9D0′;z[0x252D]=’A9D1′;z[0x252E]=’A9D2′;z[0x252F]=’A9D3′;z[0x2530]=’A9D4′;z[0x2531]=’A9D5′;z[0x2532]=’A9D6′;z[0x2533]=’A9D7′;z[0x2534]=’A9D8′;z[0x2535]=’A9D9′;z[0x2536]=’A9DA’;z[0x2537]=’A9DB’;z[0x2538]=’A9DC’;z[0x2539]=’A9DD’;z[0x253A]=’A9DE’;z[0x253B]=’A9DF’;z[0x253C]=’A9E0′;z[0x253D]=’A9E1′;z[0x253E]=’A9E2′;z[0x253F]=’A9E3′;z[0x2540]=’A9E4′;z[0x2541]=’A9E5′;z[0x2542]=’A9E6′;z[0x2543]=’A9E7′;z[0x2544]=’A9E8′;z[0x2545]=’A9E9′;z[0x2546]=’A9EA’;z[0x2547]=’A9EB’;z[0x2548]=’A9EC’;z[0x2549]=’A9ED’;z[0x254A]=’A9EE’;z[0x254B]=’A9EF’;z[0x25A0]=’A1F6′;z[0x25A1]=’A1F5′;z[0x25B2]=’A1F8′;z[0x25B3]=’A1F7′;z[0x25C6]=’A1F4′;z[0x25C7]=’A1F3′;z[0x25CB]=’A1F0′;z[0x25CE]=’A1F2′;z[0x25CF]=’A1F1′;z[0x2605]=’A1EF’;z[0x2606]=’A1EE’;z[0x2640]=’A1E2′;z[0x2642]=’A1E1′;z[0x3000]=’A1A1′;z[0x3001]=’A1A2′;z[0x3002]=’A1A3′;z[0x3003]=’A1A8′;z[0x3005]=’A1A9′;z[0x3008]=’A1B4′;z[0x3009]=’A1B5′;z[0x300A]=’A1B6′;z[0x300B]=’A1B7′;z[0x300C]=’A1B8′;z[0x300D]=’A1B9′;z[0x300E]=’A1BA’;z[0x300F]=’A1BB’;z[0x3010]=’A1BE’;z[0x3011]=’A1BF’;z[0x3013]=’A1FE’;z[0x3014]=’A1B2′;z[0x3015]=’A1B3′;z[0x3016]=’A1BC’;z[0x3017]=’A1BD’;z[0x3041]=’A4A1′;z[0x3042]=’A4A2′;z[0x3043]=’A4A3′;z[0x3044]=’A4A4′;z[0x3045]=’A4A5′;z[0x3046]=’A4A6′;z[0x3047]=’A4A7′;z[0x3048]=’A4A8′;z[0x3049]=’A4A9′;z[0x304A]=’A4