js代码-js代码外包-北京js代码外包

搜 索

Search:js代码


js ECMAScript 引用类型js代码

ECMAScript 引用类型 引用类型通常叫做类(class)。 本教程会讨论大量的 ECMAScript 预定义引用类型。 引用类型 引用类型通常叫做类(class),也就是说,遇到引用值ECMAScript 引用类型引用类型通常叫做类(class)。本教程会讨论大量的 ECMAScript 预定义引用类型。引用类型引用类型通常叫做类(class),也就是说,遇到引用值,所处理的就是对象。本教程会讨论大量的 ECMAScript 预定义引用类型。从现在起,将重点讨论与已经讨论过的原始类型紧密相关的引用类型。注意:从传统意义上来说,ECMAScript 并不真正具有类。事实上,除了说明不存在类,在 ECMA-262 中根本没有出现“类”这个词。ECMAScript 定义了“对象定义”,逻辑上等价于其他程序设计语言中的类。提示:本教程将使用术语“对象”。对象是由 new 运算符加上要实例化的对象的名字创建的。例如,下面的代码创建 Object 对象的实例:var o = new Object();这种语法与 Java 语言的相似,不过当有不止一个参数时,ECMAScript 要求使用括号。如果没有参数,如以下代码所示,括号可以省略:var o = new Object;注意:尽管括号不是必需的,但是为了避免混乱,最好使用括号。提示:我们会在对象基础这一章中更深入地探讨对象及其行为。这一节的重点是具有等价的原始类型的引用类型。Object 对象Object 对象自身用处不大,不过在了解其他类之前,还是应该了解它。因为 ECMAScript 中的 Object 对象与 Java 中的 java.lang.Object 相似,ECMAScript 中的所有对象都由这个对象继承而来,Object 对象中的所有属性和方法都会出现在其他对象中,所以理解了 Object 对象,就可以更好地理解其他对象。Object 对象具有下列属性:constructor对创建对象的函数的引用(指针)。对于 Object 对象,该指针指向原始的 Object() 函数。Prototype对该对象的对象原型的引用。对于所有的对象,它默认返回 Object 对象的一个实例。Object 对象还具有几个方法:hasOwnProperty(property)判断对象是否有某个特定的属性。必须用字符串指定该属性。(例如,o.hasOwnProperty("name"))IsPrototypeOf(object)判断该对象是否为另一个对象的原型。PropertyIsEnumerable判断给定的属性是否可以用 for...in 语句进行枚举。ToString()返回对象的原始字符串表示。对于 Object 对象,ECMA-262 没有定义这个值,所以不同的 ECMAScript 实现具有不同的值。ValueOf()返回最适合该对象的原始值。对于许多对象,该方法返回的值都与 ToString() 的返回值相同。注释:上面列出的每种属性和方法都会被其他对象覆盖。Boolean 对象Boolean 对象是 Boolean 原始类型的引用类型。要创建 Boolean 对象,只需要传递 Boolean 值作为参数:var oBooleanObject = new Boolean(true);Boolean 对象将覆盖 Object 对象的 ValueOf() 方法,返回原始值,即 true 和 false。ToString() 方法也会被覆盖,返回字符串 "true" 或 "false"。遗憾的是,在 ECMAScript 中很少使用 Boolean 对象,即使使用,也不易理解。问题通常出现在 Boolean 表达式中使用 Boolean 对象时。例如:var oFalseObject = new Boolean(false);var bResult = oFalseObject && true;//输出 true在这段代码中,用 false 值创建 Boolean 对象。然后用这个值与原始值 true 进行 AND 操作。在 Boolean 运算中,false 和 true 进行 AND 操作的结果是 false。不过,在这行代码中,计算的是 oFalseObject,而不是它的值 false。正如前面讨论过的,在 Boolean 表达式中,所有对象都会被自动转换为 true,所以 oFalseObject 的值是 true。然后 true 再与 true 进行 AND 操作,结果为 true。注意:虽然你应该了解 Boolean 对象的可用性,不过最好还是使用 Boolean 原始值,避免发生这一节提到的问题。参阅如需更多有关 Boolean 对象的信息,请访问 JavaScript Boolean 对象参考手册。Number 对象正如你可能想到的,Number 对象是 Number 原始类型的引用类型。要创建 Number 对象,采用下列代码:var oNumberObject = new Number(68);您应该已认出本章前面小节中讨论特殊值(如 Number.MAX_VALUE)时提到的 Number 对象。所有特殊值都是 Number 对象的静态属性。要得到数字对象的 Number 原始值,只需要使用 valueOf() 方法:var iNumber = oNumberObject.valueOf();当然,Number 类也有 toString() 方法,在讨论类型转换的小节中已经详细讨论过该方法。除了从 Object 对象继承的标准方法外,Number 对象还有几个处理数值的专用方法。toFixed() 方法toFixed() 方法返回的是具有指定位数小数的数字的字符串表示。例如:var oNumberObject = new Number(68);alert(oNumberObject.toFixed(2));//输出 "68.00"在这里,toFixed() 方法的参数是 2,说明应该显示两位小数。该方法返回 "68.00",空的字符串位由 0 来补充。对于处理货币的应用程序,该方法非常有用。toFixed() 方法能表示具有 0 到 20 位小数的数字,超过这个范围的值会引发错误。toExponential() 方法与格式化数字相关的另一个方法是 toExponential(),它返回的是用科学计数法表示的数字的字符串形式。与 toFixed() 方法相似,toExponential() 方法也有一个参数,指定要输出的小数的位数。例如:var oNumberObject = new Number(68);alert(oNumberObject.toExponential(1));//输出 "6.8e+1"这段代码的结果是 "6.8e+1",前面解释过,它表示 6.8x10<sup>1</sup>。问题是,如果不知道要用哪种形式(预定形式或指数形式)表示数字怎么办?可以用 toPrecision() 方法。toPrecision() 方法toPrecision() 方法根据最有意义的形式来返回数字的预定形式或指数形式。它有一个参数,即用于表示数的数字总数(不包括指数)。例如,var oNumberObject = new Number(68);alert(oNumberObject.toPrecision(1));//输出 "7e+1"这段代码的任务是用一位数字表示数字 68,结果为 "7e+1",以另外的形式表示即 70。的确,toPrecision() 方法会对数进行舍入。不过,如果用 2 位数字表示 68,就容易多了:var oNumberObject = new Number(68);alert(oNumberObject.toPrecision(2));//输出 "68"当然,输出的是 "68",因为这正是该数的准确表示。不过,如果指定的位数多于需要的位数又如何呢?var oNumberObject = new Number(68);alert(oNumberObject.toPrecision(3));//输出 "68.0"在这种情况下,toPrecision(3) 等价于 toFixed(1),输出的是 "68.0"。toFixed()、toExponential() 和 toPrecision() 方法都会进行舍入操作,以便用正确的小数位数正确地表示一个数。提示:与 Boolean 对象相似,Number 对象也很重要,不过应该少用这种对象,以避免潜在的问题。只要可能,都使用数字的原始表示法。参阅如需更多有关 Number 对象的信息,请访问 JavaScript Number 对象参考手册。String 对象String 对象是 String 原始类型的对象表示法,它是以下方式创建的:var oStringObject = new String("hello world");String 对象的 valueOf() 方法和 toString() 方法都会返回 String 类型的原始值:alert(oStringObject.valueOf() == oStringObject.toString());//输出 "true"如果运行这段代码,输出是 "true",说明这些值真的相等。注释:String 对象是 ECMAScript 中比较复杂的引用类型之一。同样,本节的重点只是 String 类的基本功能。更多的高级功能请阅读本教程相关的章节,或参阅 JavaScript String 对象参考手册。length 属性String 对象具有属性 length,它是字符串中的字符个数:var oStringObject = new String("hello world");alert(oStringObject.length);//输出 "11"这个例子输出的是 "11",即 "hello world" 中的字符个数。注意,即使字符串包含双字节的字符(与 ASCII 字符相对,ASCII 字符只占用一个字节),每个字符也只算一个字符。charAt() 和 charCodeAt() 方法String 对象还拥有大量的方法。首先,两个方法 charAt() 和 charCodeAt() 访问的是字符串中的单个字符。这两个方法都有一个参数,即要操作的字符的位置。charAt() 方法返回的是包含指定位置处的字符的字符串:var oStringObject = new String("hello world");alert(oStringObject.charAt(1));//输出 "e"在字符串 "hello world" 中,位置 1 处的字符是 "e"。在“ECMAScript 原始类型”这一节中我们讲过,第一个字符的位置是 0,第二个字符的位置是 1,依此类推。因此,调用 charAt(1) 返回的是 "e"。如果想得到的不是字符,而是字符代码,那么可以调用 charCodeAt() 方法:var oStringObject = new String("hello world");alert(oStringObject.charCodeAt(1));//输出 "101"这个例子输出 "101",即小写字母 "e" 的字符代码。concat() 方法接下来是 concat() 方法,用于把一个或多个字符串连接到 String 对象的原始值上。该方法返回的是 String 原始值,保持原始的 String 对象不变:var oStringObject = new String("hello ");var sResult = oStringObject.concat("world");alert(sResult);//输出 "hello world"alert(oStringObject);//输出 "hello "在上面这段代码中,调用 concat() 方法返回的是 "hello world",而 String 对象存放的仍然是 "hello "。出于这种原因,较常见的是用加号(+)连接字符串,因为这种形式从逻辑上表明了真正的行为:var oStringObject = new String("hello ");var sResult = oStringObject + "world";alert(sResult);//输出 "hello world"alert(oStringObject);//输出 "hello "indexOf() 和 lastIndexOf() 方法迄今为止,已讨论过连接字符串的方法,访问字符串中的单个字符的方法。不过如果无法确定在某个字符串中是否确实存在一个字符,应该调用什么方法呢?这时,可调用 indexOf() 和 lastIndexOf() 方法。indexOf() 和 lastIndexOf() 方法返回的都是指定的子串在另一个字符串中的位置,如果没有找不到子串,则返回 -1。这两个方法的不同之处在于,indexOf() 方法是从字符串的开头(位置 0)开始检索字符串,而 lastIndexOf() 方法则是从字符串的结尾开始检索子串。例如:var oStringObject = new String("hello world!");alert(oStringObject.indexOf("o"));输出 "4"alert(oStringObject.lastIndexOf("o"));输出 "7"在这里,第一个 "o" 字符串出现在位置 4,即 "hello" 中的 "o";最后一个 "o" 出现在位置 7,即 "world" 中的 "o"。如果该字符串中只有一个 "o" 字符串,那么 indexOf() 和 lastIndexOf() 方法返回的位置相同。localeCompare() 方法下一个方法是 localeCompare(),对字符串进行排序。该方法有一个参数 - 要进行比较的字符串,返回的是下列三个值之一:如果 String 对象按照字母顺序排在参数中的字符串之前,返回负数。如果 String 对象等于参数中的字符串,返回 0如果 String 对象按照字母顺序排在参数中的字符串之后,返回正数。注释:如果返回负数,那么最常见的是 -1,不过真正返回的是由实现决定的。如果返回正数,那么同样的,最常见的是 1,不过真正返回的是由实现决定的。示例如下:var oStringObject = new String("yellow");alert(oStringObject.localeCompare("brick"));//输出 "1"alert(oStringObject.localeCompare("yellow"));//输出 "0"alert(oStringObject.localeCompare("zoo"));//输出 "-1"在这段代码中,字符串 "yellow" 与 3 个值进行了对比,即 "brick"、"yellow" 和 "zoo"。由于按照字母顺序排列,"yellow" 位于 "brick" 之后,所以 localeCompare() 返回 1;"yellow" 等于 "yellow",所以 localeCompare() 返回 0;"zoo" 位于 "yellow" 之后,localeCompare() 返回 -1。再强调一次,由于返回的值是由实现决定的,所以最好以下面的方式调用 localeCompare() 方法:var oStringObject1 = new String("yellow");var oStringObject2 = new String("brick");var iResult = oStringObject1.localeCompare(oStringObject2);if(iResult < 0) {alert(oStringObject1 + " comes before " + oStringObject2);} else if (iResult > 0) {alert(oStringObject1 + " comes after " + oStringObject2);} else {alert("The two strings are equal");}采用这种结构,可以确保这段代码在所有实现中都能正确运行。localeCompare() 方法的独特之处在于,实现所处的区域(locale,兼指国家/地区和语言)确切说明了这种方法运行的方式。在美国,英语是 ECMAScript 实现的标准语言,localeCompare() 是区分大小写的,大写字母在字母顺序上排在小写字母之后。不过,在其他区域,情况可能并非如此。slice() 和 substring()ECMAScript 提供了两种方法从子串创建字符串值,即 slice() 和 substring()。这两种方法返回的都是要处理的字符串的子串,都接受一个或两个参数。第一个参数是要获取的子串的起始位置,第二个参数(如果使用的话)是要获取子串终止前的位置(也就是说,获取终止位置处的字符不包括在返回的值内)。如果省略第二个参数,终止位就默认为字符串的长度。与 concat() 方法一样,slice() 和 substring() 方法都不改变 String 对象自身的值。它们只返回原始的 String 值,保持 String 对象不变
标签:

js ECMAScript 定义类或对象js代码

ECMAScript 定义类或对象 使用预定义对象只是面向对象语言的能力的一部分,它真正强大之处在于能够创建自己专用的类和对象。 ECMAScript 拥有很多创建对象或类的方法。 工厂方式ECMAScript 定义类或对象使用预定义对象只是面向对象语言的能力的一部分,它真正强大之处在于能够创建自己专用的类和对象。ECMAScript 拥有很多创建对象或类的方法。工厂方式原始的方式因为对象的属性可以在对象创建后动态定义,所有许多开发者都在 JavaScript 最初引入时编写类似下面的代码:var oCar = new Object;oCar.color = "blue";oCar.doors = 4;oCar.mpg = 25;oCar.showColor = function() {alert(this.color);};TIY在上面的代码中,创建对象 car。然后给它设置几个属性:它的颜色是蓝色,有四个门,每加仑油可以跑 25 英里。最后一个属性实际上是指向函数的指针,意味着该属性是个方法。执行这段代码后,就可以使用对象 car。不过这里有一个问题,就是可能需要创建多个 car 的实例。解决方案:工厂方式要解决该问题,开发者创造了能创建并返回特定类型的对象的工厂函数(factory function)。例如,函数 createCar() 可用于封装前面列出的创建 car 对象的操作:function createCar() {var oTempCar = new Object;oTempCar.color = "blue";oTempCar.doors = 4;oTempCar.mpg = 25;oTempCar.showColor = function() {alert(this.color);};return oTempCar;}var oCar1 = createCar();var oCar2 = createCar();TIY在这里,第一个例子中的所有代码都包含在 createCar() 函数中。此外,还有一行额外的代码,返回 car 对象(oTempCar)作为函数值。调用此函数,将创建新对象,并赋予它所有必要的属性,复制出一个我们在前面说明过的 car 对象。因此,通过这种方法,我们可以很容易地创建 car 对象的两个版本(oCar1 和 oCar2),它们的属性完全一样。为函数传递参数我们还可以修改 createCar() 函数,给它传递各个属性的默认值,而不是简单地赋予属性默认值:function createCar(sColor,iDoors,iMpg) {var oTempCar = new Object;oTempCar.color = sColor;oTempCar.doors = iDoors;oTempCar.mpg = iMpg;oTempCar.showColor = function() {alert(this.color);};return oTempCar;}var oCar1 = createCar("red",4,23);var oCar2 = createCar("blue",3,25);oCar1.showColor();//输出 "red"oCar2.showColor();//输出 "blue"TIY给 createCar() 函数加上参数,即可为要创建的 car 对象的 color、doors 和 mpg 属性赋值。这使两个对象具有相同的属性,却有不同的属性值。在工厂函数外定义对象的方法虽然 ECMAScript 越来越正式化,但创建对象的方法却被置之不理,且其规范化至今还遭人反对。一部分是语义上的原因(它看起来不像使用带有构造函数 new 运算符那么正规),一部分是功能上的原因。功能原因在于用这种方式必须创建对象的方法。前面的例子中,每次调用函数 createCar(),都要创建新函数 showColor(),意味着每个对象都有自己的 showColor() 版本。而事实上,每个对象都共享同一个函数。有些开发者在工厂函数外定义对象的方法,然后通过属性指向该方法,从而避免这个问题:`function showColor() {alert(this.color);}`function createCar(sColor,iDoors,iMpg) {var oTempCar = new Object;oTempCar.color = sColor;oTempCar.doors = iDoors;oTempCar.mpg = iMpg;`oTempCar.showColor = showColor;`return oTempCar;}var oCar1 = createCar("red",4,23);var oCar2 = createCar("blue",3,25);oCar1.showColor();//输出 "red"oCar2.showColor();//输出 "blue"TIY在上面这段重写的代码中,在函数 createCar() 之前定义了函数 showColor()。在 createCar() 内部,赋予对象一个指向已经存在的 showColor() 函数的指针。从功能上讲,这样解决了重复创建函数对象的问题;但是从语义上讲,该函数不太像是对象的方法。所有这些问题都引发了开发者定义的构造函数的出现。构造函数方式创建构造函数就像创建工厂函数一样容易。第一步选择类名,即构造函数的名字。根据惯例,这个名字的首字母大写,以使它与首字母通常是小写的变量名分开。除了这点不同,构造函数看起来很像工厂函数。请考虑下面的例子:function Car(sColor,iDoors,iMpg) {`this`.color = sColor;`this`.doors = iDoors;`this`.mpg = iMpg;`this`.showColor = function() {alert(this.color);};}var oCar1 = `new` Car("red",4,23);var oCar2 = `new` Car("blue",3,25);TIY下面为您解释上面的代码与工厂方式的差别。首先在构造函数内没有创建对象,而是使用 this 关键字。使用 new 运算符构造函数时,在执行第一行代码前先创建一个对象,只有用 this 才能访问该对象。然后可以直接赋予 this 属性,默认情况下是构造函数的返回值(不必明确使用 return 运算符)。现在,用 new 运算符和类名 Car 创建对象,就更像 ECMAScript 中一般对象的创建方式了。你也许会问,这种方式在管理函数方面是否存在于前一种方式相同的问题呢?是的。就像工厂函数,构造函数会重复生成函数,为每个对象都创建独立的函数版本。不过,与工厂函数相似,也可以用外部函数重写构造函数,同样地,这么做语义上无任何意义。这正是下面要讲的原型方式的优势所在。原型方式该方式利用了对象的 prototype 属性,可以把它看成创建新对象所依赖的原型。这里,首先用空构造函数来设置类名。然后所有的属性和方法都被直接赋予 prototype 属性。我们重写了前面的例子,代码如下:function Car() {}Car.prototype.color = "blue";Car.prototype.doors = 4;Car.prototype.mpg = 25;Car.prototype.showColor = function() {alert(this.color);};var oCar1 = new Car();var oCar2 = new Car();TIY在这段代码中,首先定义构造函数(Car),其中无任何代码。接下来的几行代码,通过给 Car 的 prototype 属性添加属性去定义 Car 对象的属性。调用 new Car() 时,原型的所有属性都被立即赋予要创建的对象,意味着所有 Car 实例存放的都是指向 showColor() 函数的指针。从语义上讲,所有属性看起来都属于一个对象,因此解决了前面两种方式存在的问题。此外,使用这种方式,还能用 instanceof 运算符检查给定变量指向的对象的类型。因此,下面的代码将输出 TRUE:alert(oCar1 instanceof Car);//输出 "true"原型方式的问题原型方式看起来是个不错的解决方案。遗憾的是,它并不尽如人意。首先,这个构造函数没有参数。使用原型方式,不能通过给构造函数传递参数来初始化属性的值,因为 Car1 和 Car2 的 color 属性都等于 "blue",doors 属性都等于 4,mpg 属性都等于 25。这意味着必须在对象创建后才能改变属性的默认值,这点很令人讨厌,但还没完。真正的问题出现在属性指向的是对象,而不是函数时。函数共享不会造成问题,但对象却很少被多个实例共享。请思考下面的例子:function Car() {}Car.prototype.color = "blue";Car.prototype.doors = 4;Car.prototype.mpg = 25;`Car.prototype.drivers = new Array("Mike","John");`Car.prototype.showColor = function() {alert(this.color);};var oCar1 = new Car();var oCar2 = new Car();`oCar1.drivers.push("Bill");`alert(oCar1.drivers);//输出 "Mike,John,Bill"alert(oCar2.drivers);//输出 "Mike,John,Bill"TIY上面的代码中,属性 drivers 是指向 Array 对象的指针,该数组中包含两个名字 "Mike" 和 "John"。由于 drivers 是引用值,Car 的两个实例都指向同一个数组。这意味着给 oCar1.drivers 添加值 "Bill",在 oCar2.drivers 中也能看到。输出这两个指针中的任何一个,结果都是显示字符串 "Mike,John,Bill"。由于创建对象时有这么多问题,你一定会想,是否有种合理的创建对象的方法呢?答案是有,需要联合使用构造函数和原型方式。混合的构造函数/原型方式联合使用构造函数和原型方式,就可像用其他程序设计语言一样创建对象。这种概念非常简单,即用构造函数定义对象的所有非函数属性,用原型方式定义对象的函数属性(方法)。结果是,所有函数都只创建一次,而每个对象都具有自己的对象属性实例。我们重写了前面的例子,代码如下:function Car(sColor,iDoors,iMpg) {this.color = sColor;this.doors = iDoors;this.mpg = iMpg;this.drivers = new Array("Mike","John");}Car.prototype.showColor = function() {alert(this.color);};var oCar1 = new Car("red",4,23);var oCar2 = new Car("blue",3,25);oCar1.drivers.push("Bill");alert(oCar1.drivers);//输出 "Mike,John,Bill"alert(oCar2.drivers);//输出 "Mike,John"TIY现在就更像创建一般对象了。所有的非函数属性都在构造函数中创建,意味着又能够用构造函数的参数赋予属性默认值了。因为只创建 showColor() 函数的一个实例,所以没有内存浪费。此外,给 oCar1 的 drivers 数组添加 "Bill" 值,不会影响到 oCar2 的数组,所以输出这些数组的值时,oCar1.drivers 显示的是 "Mike,John,Bill",而 oCar2.drivers 显示的是 "Mike,John"。因为使用了原型方式,所以仍然能利用 instanceof 运算符来判断对象的类型。这种方式是 ECMAScript 采用的主要方式,它具有其他方式的特性,却没有他们的副作用。不过,有些开发者仍觉得这种方法不够完美。动态原型方法对于习惯使用其他语言的开发者来说,使用混合的构造函数/原型方式感觉不那么和谐。毕竟,定义类时,大多数面向对象语言都对属性和方法进行了视觉上的封装。请考虑下面的 Java 类:class Car {public String color = "blue";public int doors = 4;public int mpg = 25;public Car(String color, int doors, int mpg) {this.color = color;this.doors = doors;this.mpg = mpg;}public void showColor() {System.out.println(color);}}Java 很好地打包了 Car 类的所有属性和方法,因此看见这段代码就知道它要实现什么功能,它定义了一个对象的信息。批评混合的构造函数/原型方式的人认为,在构造函数内部找属性,在其外部找方法的做法不合逻辑。因此,他们设计了动态原型方法,以提供更友好的编码风格。动态原型方法的基本想法与混合的构造函数/原型方式相同,即在构造函数内定义非函数属性,而函数属性则利用原型属性定义。唯一的区别是赋予对象方法的位置。下面是用动态原型方法重写的 Car 类:function Car(sColor,iDoors,iMpg) {this.color = sColor;this.doors = iDoors;this.mpg = iMpg;this.drivers = new Array("Mike","John");if (`typeof Car._initialized == "undefined"`) {Car.prototype.showColor = function() {alert(this.color);};`Car._initialized = true;`}}TIY直到检查 typeof Car._initialized 是否等于 "undefined" 之前,这个构造函数都未发生变化。这行代码是动态原型方法中最重要的部分。如果这个值未定义,构造函数将用原型方式继续定义对象的方法,然后把 Car._initialized 设置为 true。如果这个值定义了(它的值为 true 时,typeof 的值为 Boolean),那么就不再创建该方法。简而言之,该方法使用标志(_initialized)来判断是否已给原型赋予了任何方法。该方法只创建并赋值一次,传统的 OOP 开发者会高兴地发现,这段代码看起来更像其他语言中的类定义了。混合工厂方式这种方式通常是在不能应用前一种方式时的变通方法。它的目的是创建假构造函数,只返回另一种对象的新实例。这段代码看起来与工厂函数非常相似:function Car() {`var oTempCar = new Object;`oTempCar.color = "blue";oTempCar.doors = 4;oTempCar.mpg = 25;oTempCar.showColor = function() {alert(this.color);};return oTempCar;}TIY与经典方式不同,这种方式使用 new 运算符,使它看起来像真正的构造函数:var car = new Car();由于在 Car() 构造函数内部调用了 new 运算符,所以将忽略第二个 new 运算符(位于构造函数之外),在构造函数内部创建的对象被传递回变量 car。这种方式在对象方法的内部管理方面与经典方式有着相同的问题。强烈建议:除非万不得已,还是避免使用这种方式。采用哪种方式如前所述,目前使用最广泛的是混合的构造函数/原型方式。此外,动态原始方法也很流行,在功能上与构造函数/原型方式等价。可以采用这两种方式中的任何一种。不过不要单独使用经典的构造函数或原型方式,因为这样会给代码引入问题。实例对象令人感兴趣的一点是用它们解决问题的方式。ECMAScript 中最常见的一个问题是字符串连接的性能。与其他语言类似,ECMAScript 的字符串是不可变的,即它们的值不能改变。请考虑下面的代码:var str = "hello ";str += "world";实际上,这段代码在幕后执行的步骤如下:创建存储 "hello " 的字符串。创建存储 "world" 的字符串。创建存储连接结果的字符串。把 str 的当前内容复制到结果中。把 "world" 复制到结果中。更新 str,使它指向结果。每次完成字符串连接都会执行
标签:

js ECMAScript 对象作用域js代码

ECMAScript 对象作用域 作用域指的是变量的适用范围。 公用、私有和受保护作用域 概念 在传统的面向对象程序设计中,主要关注于公用和私有作用域。公用作用域中的对象属性可以从对象外部访问ECMAScript 对象作用域作用域指的是变量的适用范围。公用、私有和受保护作用域概念在传统的面向对象程序设计中,主要关注于公用和私有作用域。公用作用域中的对象属性可以从对象外部访问,即开发者创建对象的实例后,就可使用它的公用属性。而私有作用域中的属性只能在对象内部访问,即对于外部世界来说,这些属性并不存在。这意味着如果类定义了私有属性和方法,则它的子类也不能访问这些属性和方法。受保护作用域也是用于定义私有的属性和方法,只是这些属性和方法还能被其子类访问。ECMAScript 只有公用作用域对 ECMAScript 讨论上面这些作用域几乎毫无意义,因为 ECMAScript 中只存在一种作用域 - 公用作用域。ECMAScript 中的所有对象的所有属性和方法都是公用的。因此,定义自己的类和对象时,必须格外小心。记住,所有属性和方法默认都是公用的!建议性的解决方法许多开发者都在网上提出了有效的属性作用域模式,解决了 ECMAScript 的这种问题。由于缺少私有作用域,开发者确定了一个规约,说明哪些属性和方法应该被看做私有的。这种规约规定在属性前后加下划线:obj._color_ = "blue";这段代码中,属性 color 是私有的。注意,下划线并不改变属性是公用属性的事实,它只是告诉其他开发者,应该把该属性看作私有的。有些开发者还喜欢用单下划线说明私有成员,例如:obj._color。静态作用域静态作用域定义的属性和方法任何时候都能从同一位置访问。在 Java 中,类可具有属性和方法,无需实例化该类的对象,即可访问这些属性和方法,例如 java.net.URLEncoder 类,它的函数 encode() 就是静态方法。ECMAScript 没有静态作用域严格来说,ECMAScript 并没有静态作用域。不过,它可以给构造函数提供属性和方法。还记得吗,构造函数只是函数。函数是对象,对象可以有属性和方法。例如:function sayHello() {alert("hello");}sayHello.alternate = function() {alert("hi");}sayHello();//输出 "hello"sayHello.alternate();//输出 "hi"TIY这里,方法 alternate() 实际上是函数 sayHello 的方法。可以像调用常规函数一样调用 sayHello() 输出 "hello",也可以调用 sayHello.alternate() 输出 "hi"。即使如此,alternate() 也是 sayHello() 公用作用域中的方法,而不是静态方法。关键字 thisthis 的功能在 ECMAScript 中,要掌握的最重要的概念之一是关键字 this 的用法,它用在对象的方法中。关键字 this 总是指向调用该方法的对象,例如:var oCar = new Object;oCar.color = "red";oCar.showColor = function() {alert(`this.color`);};oCar.showColor();//输出 "red"TIY在上面的代码中,关键字 this 用在对象的 showColor() 方法中。在此环境中,this 等于 oCar。下面的代码与上面的代码的功能相同:var oCar = new Object;oCar.color = "red";oCar.showColor = function() {alert(`oCar.color`);};oCar.showColor();//输出 "red"TIY使用 this 的原因为什么使用 this 呢?因为在实例化对象时,总是不能确定开发者会使用什么样的变量名。使用 this,即可在任何多个地方重用同一个函数。请思考下面的例子:function showColor() {alert(`this.color`);};var oCar1 = new Object;oCar1.color = "red";oCar1.showColor = showColor;var oCar2 = new Object;oCar2.color = "blue";oCar2.showColor = showColor;oCar1.showColor();//输出 "red"oCar2.showColor();//输出 "blue"TIY在上面的代码中,首先用 this 定义函数 showColor(),然后创建两个对象(oCar1 和 oCar2),一个对象的 color 属性被设置为 "red",另一个对象的 color 属性被设置为 "blue"。两个对象都被赋予了属性 showColor,指向原始的 showColor () 函数(注意这里不存在命名问题,因为一个是全局函数,而另一个是对象的属性)。调用每个对象的 showColor(),oCar1 输出是 "red",而 oCar2 的输出是 "blue"。这是因为调用 oCar1.showColor() 时,函数中的 this 关键字等于 oCar1。调用 oCar2.showColor() 时,函数中的 this 关键字等于 oCar2。注意,引用对象的属性时,必须使用 this 关键字。例如,如果采用下面的代码,showColor() 方法不能运行:function showColor() {alert(`color`);};如果不用对象或 this 关键字引用变量,ECMAScript 就会把它看作局部变量或全局变量。然后该函数将查找名为 color 的局部或全局变量,但是不会找到。结果如何呢?该函数将在警告中显示 "null"。
标签:

js ECMAScript 位运算符js代码

ECMAScript 位运算符 位运算符是在数字底层(即表示数字的 32 个数位)进行操作的。 重温整数 ECMAScript 整数有两种类型,即有符号整数(允许用正数和负数)和无符号整数(只ECMAScript 位运算符位运算符是在数字底层(即表示数字的 32 个数位)进行操作的。重温整数ECMAScript 整数有两种类型,即有符号整数(允许用正数和负数)和无符号整数(只允许用正数)。在 ECMAScript 中,所有整数字面量默认都是有符号整数,这意味着什么呢?有符号整数使用 31 位表示整数的数值,用第 32 位表示整数的符号,0 表示正数,1 表示负数。数值范围从 -2147483648 到 2147483647。可以以两种不同的方式存储二进制形式的有符号整数,一种用于存储正数,一种用于存储负数。正数是以真二进制形式存储的,前 31 位中的每一位都表示 2 的幂,从第 1 位(位 0)开始,表示 2<sup>0</sup>,第 2 位(位 1)表示 2<sup>1</sup>。没用到的位用 0 填充,即忽略不计。例如,下图展示的是数 18 的表示法。18 的二进制版本只用了前 5 位,它们是这个数字的有效位。把数字转换成二进制字符串,就能看到有效位:var iNum = 18;alert(iNum.toString(2));//输出 "10010"这段代码只输出 "10010",而不是 18 的 32 位表示。其他的数位并不重要,因为仅使用前 5 位即可确定这个十进制数值。如下图所示:负数也存储为二进制代码,不过采用的形式是二进制补码。计算数字二进制补码的步骤有三步:确定该数字的非负版本的二进制表示(例如,要计算 -18的二进制补码,首先要确定 18 的二进制表示)求得二进制反码,即要把 0 替换为 1,把 1 替换为 0在二进制反码上加 1要确定 -18 的二进制表示,首先必须得到 18 的二进制表示,如下所示:0000 0000 0000 0000 0000 0000 0001 0010接下来,计算二进制反码,如下所示:1111 1111 1111 1111 1111 1111 1110 1101最后,在二进制反码上加 1,如下所示:1111 1111 1111 1111 1111 1111 1110 11011---------------------------------------1111 1111 1111 1111 1111 1111 1110 1110因此,-18 的二进制表示即 1111 1111 1111 1111 1111 1111 1110 1110。记住,在处理有符号整数时,开发者不能访问 31 位。有趣的是,把负整数转换成二进制字符串后,ECMAScript 并不以二进制补码的形式显示,而是用数字绝对值的标准二进制代码前面加负号的形式输出。例如:var iNum = -18;alert(iNum.toString(2));//输出 "-10010"这段代码输出的是 "-10010",而非二进制补码,这是为避免访问位 31。为了简便,ECMAScript 用一种简单的方式处理整数,使得开发者不必关心它们的用法。另一方面,无符号整数把最后一位作为另一个数位处理。在这种模式中,第 32 位不表示数字的符号,而是值 2<sup>31</sup>。由于这个额外的位,无符号整数的数值范围为 0 到 4294967295。对于小于 2147483647 的整数来说,无符号整数看来与有符号整数一样,而大于 2147483647 的整数则要使用位 31(在有符号整数中,这一位总是 0)。把无符号整数转换成字符串后,只返回它们的有效位。注意:所有整数字面量都默认存储为有符号整数。只有 ECMAScript 的位运算符才能创建无符号整数。位运算 NOT位运算 NOT 由否定号(~)表示,它是 ECMAScript 中为数不多的与二进制算术有关的运算符之一。位运算 NOT 是三步的处理过程:把运算数转换成 32 位数字把二进制数转换成它的二进制反码把二进制数转换成浮点数例如:var iNum1 = 25;//25 等于 00000000000000000000000000011001`var iNum2 = ~iNum1;`//转换为 11111111111111111111111111100110alert(iNum2);//输出 "-26"位运算 NOT 实质上是对数字求负,然后减 1,因此 25 变 -26。用下面的方法也可以得到同样的方法:var iNum1 = 25;var iNum2 = -iNum1 -1;alert(iNum2);//输出 -26位运算 AND位运算 AND 由和号(&)表示,直接对数字的二进制形式进行运算。它把每个数字中的数位对齐,然后用下面的规则对同一位置上的两个数位进行 AND 运算:第一个数字中的数位第二个数字中的数位结果111100010000例如,要对数字 25 和 3 进行 AND 运算,代码如下所示:var iResult = 25 & 3;alert(iResult);//输出 "1"25 和 3 进行 AND 运算的结果是 1。为什么?分析如下: 25 = 0000 0000 0000 0000 0000 0000 0001 10013 = 0000 0000 0000 0000 0000 0000 0000 0011---------------------------------------------AND = 0000 0000 0000 0000 0000 0000 0000 0001可以看出,在 25 和 3 中,只有一个数位(位 0)存放的都是 1,因此,其他数位生成的都是 0,所以结果为 1。位运算 OR位运算 OR 由符号(|)表示,也是直接对数字的二进制形式进行运算。在计算每位时,OR 运算符采用下列规则:第一个数字中的数位第二个数字中的数位结果111101011000仍然使用 AND 运算符所用的例子,对 25 和 3 进行 OR 运算,代码如下:var iResult = 25 | 3;alert(iResult);//输出 "27"25 和 3 进行 OR 运算的结果是 27:25 = 0000 0000 0000 0000 0000 0000 0001 1001 3 = 0000 0000 0000 0000 0000 0000 0000 0011--------------------------------------------OR = 0000 0000 0000 0000 0000 0000 0001 1011可以看出,在两个数字中,共有 4 个数位存放的是 1,这些数位被传递给结果。二进制代码 11011 等于 27。位运算 XOR位运算 XOR 由符号(^)表示,当然,也是直接对二进制形式进行运算。XOR 不同于 OR,当只有一个数位存放的是 1 时,它才返回 1。真值表如下:第一个数字中的数位第二个数字中的数位结果110101011000对 25 和 3 进行 XOR 运算,代码如下:var iResult = 25 ^ 3;alert(iResult);//输出 "26"25 和 3 进行 XOR 运算的结果是 26: 25 = 0000 0000 0000 0000 0000 0000 0001 10013 = 0000 0000 0000 0000 0000 0000 0000 0011---------------------------------------------XOR = 0000 0000 0000 0000 0000 0000 0001 1010可以看出,在两个数字中,共有 4 个数位存放的是 1,这些数位被传递给结果。二进制代码 11010 等于 26。左移运算左移运算由两个小于号表示(<<)。它把数字中的所有数位向左移动指定的数量。例如,把数字 2(等于二进制中的 10)左移 5 位,结果为 64(等于二进制中的 1000000):var iOld = 2;//等于二进制 10var iNew = iOld << 5;//等于二进制 1000000 十进制 64注意:在左移数位时,数字右边多出 5 个空位。左移运算用 0 填充这些空位,使结果成为完整的 32 位数字。注意:左移运算保留数字的符号位。例如,如果把 -2 左移 5 位,得到的是 -64,而不是 64。“符号仍然存储在第 32 位中吗?”是的,不过这在 ECMAScript 后台进行,开发者不能直接访问第 32 个数位。即使输出二进制字符串形式的负数,显示的也是负号形式(例如,-2 将显示 -10。)有符号右移运算有符号右移运算符由两个大于号表示(>>)。它把 32 位数字中的所有数位整体右移,同时保留该数的符号(正号或负号)。有符号右移运算符恰好与左移运算相反。例如,把 64 右移 5 位,将变为 2:var iOld = 64;//等于二进制 1000000var iNew = iOld >> 5;//等于二进制 10 十进制 2同样,移动数位后会造成空位。这次,空位位于数字的左侧,但位于符号位之后。ECMAScript 用符号位的值填充这些空位,创建完整的数字,如下图所示:无符号右移运算无符号右移运算符由三个大于号(>>>)表示,它将无符号 32 位数的所有数位整体右移。对于正数,无符号右移运算的结果与有符号右移运算一样。用有符号右移运算中的例子,把 64 右移 5 位,将变为 2:var iOld = 64;//等于二进制 1000000var iNew = iOld >>> 5;//等于二进制 10 十进制 2对于负数,情况就不同了。无符号右移运算用 0 填充所有空位。对于正数,这与有符号右移运算的操作一样,而负数则被作为正数来处理。由于无符号右移运算的结果是一个 32 位的正数,所以负数的无符号右移运算得到的总是一个非常大的数字。例如,如果把 -64 右移 5 位,将得到 134217726。如何得到这种结果的呢?要实现这一点,需要把这个数字转换成无符号的等价形式(尽管该数字本身还是有符号的),可以通过以下代码获得这种形式:var iUnsigned64 = -64 >>> 0;然后,用 Number 类型的 toString() 获取它的真正的位表示,采用的基为 2:alert(iUnsigned64.toString(2));这将生成 11111111111111111111111111000000,即有符号整数 -64 的二进制补码表示,不过它等于无符号整数 4294967232。出于这种原因,使用无符号右移运算符要小心。
标签:

js ECMAScript 修改对象js代码

ECMAScript 修改对象 通过使用 ECMAScript,不仅可以创建对象,还可以修改已有对象的行为。 prototype 属性不仅可以定义构造函数的属性和方法,还可以为本地对象添加属性ECMAScript 修改对象通过使用 ECMAScript,不仅可以创建对象,还可以修改已有对象的行为。prototype 属性不仅可以定义构造函数的属性和方法,还可以为本地对象添加属性和方法。创建新方法通过已有的方法创建新方法可以用 prototype 属性为任何已有的类定义新方法,就像处理自己的类一样。例如,还记得 Number 类的 toString() 方法吗?如果给它传递参数 16,它将输出十六进制的字符串。如果这个方法的参数是 2,那么它将输出二进制的字符串。我们可以创建一个方法,可以把数字对象直接转换为十六进制字符串。创建这个方法非常简单:Number.prototype.toHexString = function() {return this.toString(16);};在此环境中,关键字 this 指向 Number 的实例,因此可完全访问 Number 的所有方法。有了这段代码,可实现下面的操作:var iNum = 15;alert(iNum.toHexString());//输出 "F"TIY由于数字 15 等于十六进制中的 F,因此警告将显示 "F"。重命名已有方法我们还可以为已有的方法命名更易懂的名称。例如,可以给 Array 类添加两个方法 enqueue() 和 dequeue(),只让它们反复调用已有的 push() 和 shift() 方法即可:Array.prototype.enqueue = function(vItem) {this.push(vItem);};Array.prototype.dequeue = function() {return this.shift();};TIY添加与已有方法无关的方法当然,还可以添加与已有方法无关的方法。例如,假设要判断某个项在数组中的位置,没有本地方法可以做这种事情。我们可以轻松地创建下面的方法:Array.prototype.indexOf = function (vItem) {for (var i=0; i<this.length; i++) {if (vItem == this[i]) {return i;}}return -1;}该方法 indexOf() 与 String 类的同名方法保持一致,在数组中检索每个项,直到发现与传进来的项相同的项目为止。如果找到相同的项,则返回该项的位置,否则,返回 -1。有了这种定义,我们可以编写下面的代码:var aColors = new Array("red","green","blue");alert(aColors.indexOf("green"));//输出 "1"TIY为本地对象添加新方法最后,如果想给 ECMAScript 中每个本地对象添加新方法,必须在 Object 对象的 prototype 属性上定义它。前面的章节我们讲过,所有本地对象都继承了 Object 对象,所以对 Object 对象做任何改变,都会反应在所有本地对象上。例如,如果想添加一个用警告输出对象的当前值的方法,可以采用下面的代码:Object.prototype.showValue = function () {alert(this.valueOf());};var str = "hello";var iNum = 25;str.showValue();//输出 "hello"iNum.showValue();//输出 "25"TIY这里,String 和 Number 对象都从 Object 对象继承了 showValue() 方法,分别在它们的对象上调用该方法,将显示 "hello" 和 "25"。重定义已有方法就像能给已有的类定义新方法一样,也可重定义已有的方法。如前面的章节所述,函数名只是指向函数的指针,因此可以轻松地指向其他函数。如果修改了本地方法,如 toString(),会出现什么情况呢?Function.prototype.toString = function() {return "Function code hidden";}前面的代码完全合法,运行结果完全符合预期:function sayHi() {alert("hi");}alert(sayHi.toString());//输出 "Function code hidden"TIY也许你还记得,Function 对象这一章中介绍过 Function 的 toString() 方法通常输出的是函数的源代码。覆盖该方法,可以返回另一个字符串(在这个例子中,可以返回 "Function code hidden")。不过,toString() 指向的原始函数怎么了呢?它将被无用存储单元回收程序回收,因为它被完全废弃了。没有能够恢复原始函数的方法,所以在覆盖原始方法前,比较安全的做法是存储它的指针,以便以后的使用。有时你甚至可能在新方法中调用原始方法:`Function.prototype.originalToString = Function.prototype.toString;`Function.prototype.toString = function() {if (this.originalToString().length > 100) {return "Function too long to display.";} else {return this.originalToString();}};TIY在这段代码中,第一行代码把对当前 toString() 方法的引用保存在属性 originalToString 中。然后用定制的方法覆盖了 toString() 方法。新方法将检查该函数源代码的长度是否大于 100。如果是,就返回错误信息,说明该函数代码太长,否则调用 originalToString() 方法,返回函数的源代码。极晚绑定(Very Late Binding)从技术上讲,根本不存在极晚绑定。本书采用该术语描述 ECMAScript 中的一种现象,即能够在对象实例化后再定义它的方法。例如:var o = new Object();Object.prototype.sayHi = function () {alert("hi");};o.sayHi();TIY在大多数程序设计语言中,必须在实例化对象之前定义对象的方法。这里,方法 sayHi() 是在创建 Object 类的一个实例之后来添加进来的。在传统语言中不仅没听说过这种操作,也没听说过该方法还会自动赋予 Object 对象的实例并能立即使用(接下来的一行)。注意:不建议使用极晚绑定方法,因为很难对其跟踪和记录。不过,还是应该了解这种可能。
标签:

js ECMAScript 变量js代码

ECMAScript 变量 请使用 var 运算符声明变量。 变量名需要遵守一些简单的规则。 声明变量 在上一节中我们讲解过,ECMAScript 中的变量是用 var 运算符(variablECMAScript 变量请使用 var 运算符声明变量。变量名需要遵守一些简单的规则。声明变量在上一节中我们讲解过,ECMAScript 中的变量是用 var 运算符(variable 的缩写)加变量名定义的。例如:var test = "hi";在这个例子中,声明了变量 test,并把它的值初始化为 "hi"(字符串)。由于 ECMAScript 是弱类型的,所以解释程序会为 test 自动创建一个字符串值,无需明确的类型声明。还可以用一个 var 语句定义两个或多个变量:var test1 = "hi", test2 = "hello";前面的代码定义了变量 test1,初始值为 "hi",还定义了变量 test2,初始值为 "hello"。不过用同一个 var 语句定义的变量不必具有相同的类型,如下所示:var test = "hi", age = 25;这个例子除了(再次)定义 test 外,还定义了 age,并把它初始化为 25。即使 test 和 age 属于两种不同的数据类型,在 ECMAScript 中这样定义也是完全合法的。与 Java 不同,ECMAScript 中的变量并不一定要初始化(它们是在幕后初始化的,将在后面讨论这一点)。因此,下面这一行代码也是有效的:var test;此外,与 Java 不同的还有变量可以存放不同类型的值。这是弱类型变量的优势。例如,可以把变量初始化为字符串类型的值,之后把它设置为数字值,如下所示:var test = "hi";alert(test);test = 55;alert(test);这段代码将毫无问题地输出字符串值和数字值。但是,如前所述,使用变量时,好的编码习惯是始终存放相同类型的值。命名变量变量名需要遵守两条简单的规则:第一个字符必须是字母、下划线(_)或美元符号($)余下的字符可以是下划线、美元符号或任何字母或数字字符下面的变量都是合法的:var test;var $test;var $1;var _$te$t2;著名的变量命名规则只是因为变量名的语法正确,并不意味着就该使用它们。变量还应遵守以下某条著名的命名规则:Camel 标记法首字母是小写的,接下来的字母都以大写字符开头。例如:var myTestValue = 0, mySecondValue = "hi";Pascal 标记法首字母是大写的,接下来的字母都以大写字符开头。例如:var MyTestValue = 0, MySecondValue = "hi";匈牙利类型标记法在以 Pascal 标记法命名的变量前附加一个小写字母(或小写字母序列),说明该变量的类型。例如,i 表示整数,s 表示字符串,如下所示“var iMyTestValue = 0, sMySecondValue = "hi";本教程采用了这些前缀,以使示例代码更易阅读:类型前缀示例数组aaValues布尔型bbFound浮点型(数字)ffValue函数fnfnMethod整型(数字)iiValue对象ooType正则表达式rerePattern字符串ssValue变型(可以是任何类型)vvValue变量声明不是必须的ECMAScript 另一个有趣的方面(也是与大多数程序设计语言的主要区别),是在使用变量之前不必声明。例如:var sTest = "hello ";sTest2 = sTest + "world";alert(sTest2);在上面的代码中,首先,sTest 被声明为字符串类型的值 "hello"。接下来的一行,用变量 sTest2 把 sTest 与字符串 "world" 连在一起。变量 sTest2 并没有用 var 运算符定义,这里只是插入了它,就像已经声明过它一样。ECMAScript 的解释程序遇到未声明过的标识符时,用该变量名创建一个全局变量,并将其初始化为指定的值。这是该语言的便利之处,不过如果不能紧密跟踪变量,这样做也很危险。最好的习惯是像使用其他程序设计语言一样,总是声明所有变量。
标签:

js ECMAScript Boolean 运算符js代码

ECMAScript Boolean 运算符 Boolean 运算符非常重要,它使得程序语言得以正常运行。 Boolean 运算符有三种:NOT、AND 和 OR。 ToBoolean 操作ECMAScript Boolean 运算符Boolean 运算符非常重要,它使得程序语言得以正常运行。Boolean 运算符有三种:NOT、AND 和 OR。ToBoolean 操作在学习各种逻辑运算符之前,让我们先了解一下 ECMAScript-262 v5 规范中描述的 ToBoolean 操作。抽象操作 ToBoolean 将其参数按照下表中的规则转换为逻辑值:参数类型结果UndefinedfalseNullfalseBoolean结果等于输入的参数(不转换)Number如果参数为 +0, -0 或 NaN,则结果为 false;否则为 true。String如果参数为空字符串,则结果为 false;否则为 true。Objecttrue逻辑 NOT 运算符在 ECMAScript 中,逻辑 NOT 运算符与 C 和 Java 中的逻辑 NOT 运算符相同,都由感叹号(!)表示。与逻辑 OR 和逻辑 AND 运算符不同的是,逻辑 NOT 运算符返回的一定是 Boolean 值。逻辑 NOT 运算符的行为如下:如果运算数是对象,返回 false如果运算数是数字 0,返回 true如果运算数是 0 以外的任何数字,返回 false如果运算数是 null,返回 true如果运算数是 NaN,返回 true如果运算数是 undefined,发生错误通常,该运算符用于控制循环:var bFound = false;var i = 0;`while (!bFound)` {if (aValue[i] == vSearchValues) {bFound = true;} else {i++;}}在这个例子中,Boolean 变量(bFound)用于记录检索是否成功。找到问题中的数据项时,bFound 将被设置为 true,!bFound 将等于 false,意味着运行将跳出 while 循环。判断 ECMAScript 变量的 Boolean 值时,也可以使用逻辑 NOT 运算符。这样做需要在一行代码中使用两个 NOT 运算符。无论运算数是什么类型,第一个 NOT 运算符返回 Boolean 值。第二个 NOT 将对该 Boolean 值求负,从而给出变量真正的 Boolean 值。var bFalse = false;var sRed = "red";var iZero = 0;var iThreeFourFive = 345;var oObject = new Object;document.write("bFalse 的逻辑值是 " + (!!bFalse));document.write("sRed 的逻辑值是 " + (!!sRed));document.write("iZero 的逻辑值是 " + (!!iZero));document.write("iThreeFourFive 的逻辑值是 " + (!!iThreeFourFive));document.write("oObject 的逻辑值是 " + (!!oObject));结果:bFalse 的逻辑值是 falsesRed 的逻辑值是 trueiZero 的逻辑值是 falseiThreeFourFive 的逻辑值是 trueoObject 的逻辑值是 true逻辑 AND 运算符在 ECMAScript 中,逻辑 AND 运算符用双和号(&&)表示:例如:var bTrue = true;var bFalse = false;var bResult = bTrue && bFalse;下面的真值表描述了逻辑 AND 运算符的行为:运算数 1运算数 2结果truetruetruetruefalsefalsefalsetruefalsefalsefalsefalse逻辑 AND 运算的运算数可以是任何类型的,不止是 Boolean 值。如果某个运算数不是原始的 Boolean 型值,逻辑 AND 运算并不一定返回 Boolean 值:如果一个运算数是对象,另一个是 Boolean 值,返回该对象。如果两个运算数都是对象,返回第二个对象。如果某个运算数是 null,返回 null。如果某个运算数是 NaN,返回 NaN。如果某个运算数是 undefined,发生错误。与 Java 中的逻辑 AND 运算相似,ECMAScript 中的逻辑 AND 运算也是简便运算,即如果第一个运算数决定了结果,就不再计算第二个运算数。对于逻辑 AND 运算来说,如果第一个运算数是 false,那么无论第二个运算数的值是什么,结果都不可能等于 true。考虑下面的例子:var bTrue = true;var bResult = (bTrue && bUnknown);//发生错误alert(bResult);//这一行不会执行这段代码在进行逻辑 AND 运算时将引发错误,因为变量 bUnknown 是未定义的。变量 bTrue 的值为 true,因为逻辑 AND 运算将继续计算变量 bUnknown。这样做就会引发错误,因为 bUnknown 的值是 undefined,不能用于逻辑 AND 运算。如果修改这个例子,把第一个数设为 false,那么就不会发生错误:var bFalse = false;var bResult = (bFalse && bUnknown);alert(bResult);//输出 "false"在这段代码中,脚本将输出逻辑 AND 运算返回的值,即字符串 "false"。即使变量 bUnknown 的值为 undefined,它也不会被计算,因为第一个运算数的值是 false。提示:在使用逻辑 AND 运算符时,必须记住它的这种简便计算特性。逻辑 OR 运算符ECMAScript 中的逻辑 OR 运算符与 Java 中的相同,都由双竖线(||)表示:var bTrue = true;var bFalse = false;var bResult = bTrue || bFalse;下面的真值表描述了逻辑 OR 运算符的行为:运算数 1运算数 2结果truetruetruetruefalsetruefalsetruetruefalsefalsefalse与逻辑 AND 运算符相似,如果某个运算数不是 Boolean 值,逻辑 OR 运算并不一定返回 Boolean 值:如果一个运算数是对象,并且该对象左边的运算数值均为 false,则返回该对象。如果两个运算数都是对象,返回第一个对象。如果最后一个运算数是 null,并且其他运算数值均为 false,则返回 null。如果最后一个运算数是 NaN,并且其他运算数值均为 false,则返回 NaN。如果某个运算数是 undefined,发生错误。与逻辑 AND 运算符一样,逻辑 OR 运算也是简便运算。对于逻辑 OR 运算符来说,如果第一个运算数值为 true,就不再计算第二个运算数。例如:var bTrue = true;var bResult = (bTrue || bUnknown);alert(bResult);//输出 "true"与前面的例子相同,变量 bUnknown 是未定义的。不过,由于变量 bTrue 的值为 true,bUnknown 不会被计算,因此输出的是 "true"。如果把 bTrue 改为 false,将发生错误:var bFalse = false;var bResult = (bFalse || bUnknown);//发生错误alert(bResult);//不会执行这一行
标签:

js ECMAScript 继承机制实现js代码

ECMAScript 继承机制实现 继承机制的实现 要用 ECMAScript 实现继承机制,您可以从要继承的基类入手。所有开发者定义的类都可作为基类。出于安全原因,本地类和宿主类不能作为基类ECMAScript 继承机制实现继承机制的实现要用 ECMAScript 实现继承机制,您可以从要继承的基类入手。所有开发者定义的类都可作为基类。出于安全原因,本地类和宿主类不能作为基类,这样可以防止公用访问编译过的浏览器级的代码,因为这些代码可以被用于恶意攻击。选定基类后,就可以创建它的子类了。是否使用基类完全由你决定。有时,你可能想创建一个不能直接使用的基类,它只是用于给子类提供通用的函数。在这种情况下,基类被看作抽象类。尽管 ECMAScript 并没有像其他语言那样严格地定义抽象类,但有时它的确会创建一些不允许使用的类。通常,我们称这种类为抽象类。创建的子类将继承超类的所有属性和方法,包括构造函数及方法的实现。记住,所有属性和方法都是公用的,因此子类可直接访问这些方法。子类还可添加超类中没有的新属性和方法,也可以覆盖超类的属性和方法。继承的方式和其他功能一样,ECMAScript 实现继承的方式不止一种。这是因为 JavaScript 中的继承机制并不是明确规定的,而是通过模仿实现的。这意味着所有的继承细节并非完全由解释程序处理。作为开发者,你有权决定最适用的继承方式。下面为您介绍几种具体的继承方式。对象冒充构想原始的 ECMAScript 时,根本没打算设计对象冒充(object masquerading)。它是在开发者开始理解函数的工作方式,尤其是如何在函数环境中使用 this 关键字后才发展出来。其原理如下:构造函数使用 this 关键字给所有属性和方法赋值(即采用类声明的构造函数方式)。因为构造函数只是一个函数,所以可使 ClassA 构造函数成为 ClassB 的方法,然后调用它。ClassB 就会收到 ClassA 的构造函数中定义的属性和方法。例如,用下面的方式定义 ClassA 和 ClassB:function ClassA(sColor) {this.color = sColor;this.sayColor = function () {alert(this.color);};}function ClassB(sColor) {}还记得吗?关键字 this 引用的是构造函数当前创建的对象。不过在这个方法中,this 指向的所属的对象。这个原理是把 ClassA 作为常规函数来建立继承机制,而不是作为构造函数。如下使用构造函数 ClassB 可以实现继承机制:function ClassB(sColor) {this.newMethod = ClassA;this.newMethod(sColor);delete this.newMethod;}在这段代码中,为 ClassA 赋予了方法 newMethod(请记住,函数名只是指向它的指针)。然后调用该方法,传递给它的是 ClassB 构造函数的参数 sColor。最后一行代码删除了对 ClassA 的引用,这样以后就不能再调用它。所有新属性和新方法都必须在删除了新方法的代码行后定义。否则,可能会覆盖超类的相关属性和方法:function ClassB(sColor, sName) {this.newMethod = ClassA;this.newMethod(sColor);delete this.newMethod;this.name = sName;this.sayName = function () {alert(this.name);};}为证明前面的代码有效,可以运行下面的例子:var objA = new ClassA("blue");var objB = new ClassB("red", "John");objA.sayColor();//输出 "blue"objB.sayColor();//输出 "red"objB.sayName();//输出 "John"对象冒充可以实现多重继承有趣的是,对象冒充可以支持多重继承。也就是说,一个类可以继承多个超类。用 UML 表示的多重继承机制如下图所示:例如,如果存在两个类 ClassX 和 ClassY,ClassZ 想继承这两个类,可以使用下面的代码:function ClassZ() {this.newMethod = ClassX;this.newMethod();delete this.newMethod;this.newMethod = ClassY;this.newMethod();delete this.newMethod;}TIY这里存在一个弊端,如果存在两个类 ClassX 和 ClassY 具有同名的属性或方法,ClassY 具有高优先级。因为它从后面的类继承。除这点小问题之外,用对象冒充实现多重继承机制轻而易举。由于这种继承方法的流行,ECMAScript 的第三版为 Function 对象加入了两个方法,即 call() 和 apply()。call() 方法call() 方法是与经典的对象冒充方法最相似的方法。它的第一个参数用作 this 的对象。其他参数都直接传递给函数自身。例如:function sayColor(sPrefix,sSuffix) {alert(sPrefix + this.color + sSuffix);};var obj = new Object();obj.color = "blue";sayColor.call(obj, "The color is ", "a very nice color indeed.");在这个例子中,函数 sayColor() 在对象外定义,即使它不属于任何对象,也可以引用关键字 this。对象 obj 的 color 属性等于 blue。调用 call() 方法时,第一个参数是 obj,说明应该赋予 sayColor() 函数中的 this 关键字值是 obj。第二个和第三个参数是字符串。它们与 sayColor() 函数中的参数 sPrefix 和 sSuffix 匹配,最后生成的消息 "The color is blue, a very nice color indeed." 将被显示出来。要与继承机制的对象冒充方法一起使用该方法,只需将前三行的赋值、调用和删除代码替换即可:function ClassB(sColor, sName) {//this.newMethod = ClassA;//this.newMethod(color);//delete this.newMethod;ClassA.call(this, sColor);this.name = sName;this.sayName = function () {alert(this.name);};}TIY这里,我们需要让 ClassA 中的关键字 this 等于新创建的 ClassB 对象,因此 this 是第一个参数。第二个参数 sColor 对两个类来说都是唯一的参数。apply() 方法apply() 方法有两个参数,用作 this 的对象和要传递给函数的参数的数组。例如:function sayColor(sPrefix,sSuffix) {alert(sPrefix + this.color + sSuffix);};var obj = new Object();obj.color = "blue";sayColor.apply(obj, new Array("The color is ", "a very nice color indeed."));这个例子与前面的例子相同,只是现在调用的是 apply() 方法。调用 apply() 方法时,第一个参数仍是 obj,说明应该赋予 sayColor() 函数中的 this 关键字值是 obj。第二个参数是由两个字符串构成的数组,与 sayColor() 函数中的参数 sPrefix 和 sSuffix 匹配,最后生成的消息仍是 "The color is blue, a very nice color indeed.",将被显示出来。该方法也用于替换前三行的赋值、调用和删除新方法的代码:function ClassB(sColor, sName) {//this.newMethod = ClassA;//this.newMethod(color);//delete this.newMethod;ClassA.apply(this, new Array(sColor));this.name = sName;this.sayName = function () {alert(this.name);};}同样的,第一个参数仍是 this,第二个参数是只有一个值 color 的数组。可以把 ClassB 的整个 arguments 对象作为第二个参数传递给 apply() 方法:function ClassB(sColor, sName) {//this.newMethod = ClassA;//this.newMethod(color);//delete this.newMethod;ClassA.apply(this, arguments);this.name = sName;this.sayName = function () {alert(this.name);};}TIY当然,只有超类中的参数顺序与子类中的参数顺序完全一致时才可以传递参数对象。如果不是,就必须创建一个单独的数组,按照正确的顺序放置参数。此外,还可使用 call() 方法。原型链(prototype chaining)继承这种形式在 ECMAScript 中原本是用于原型链的。上一章介绍了定义类的原型方式。原型链扩展了这种方式,以一种有趣的方式实现继承机制。在上一章学过,prototype 对象是个模板,要实例化的对象都以这个模板为基础。总而言之,prototype 对象的任何属性和方法都被传递给那个类的所有实例。原型链利用这种功能来实现继承机制。如果用原型方式重定义前面例子中的类,它们将变为下列形式:function ClassA() {}ClassA.prototype.color = "blue";ClassA.prototype.sayColor = function () {alert(this.color);};function ClassB() {}`ClassB.prototype = new ClassA();`原型方式的神奇之处在于突出显示的蓝色代码行。这里,把 ClassB 的 prototype 属性设置成 ClassA 的实例。这很有意思,因为想要 ClassA 的所有属性和方法,但又不想逐个将它们 ClassB 的 prototype 属性。还有比把 ClassA 的实例赋予 prototype 属性更好的方法吗?注意:调用 ClassA 的构造函数,没有给它传递参数。这在原型链中是标准做法。要确保构造函数没有任何参数。与对象冒充相似,子类的所有属性和方法都必须出现在 prototype 属性被赋值后,因为在它之前赋值的所有方法都会被删除。为什么?因为 prototype 属性被替换成了新对象,添加了新方法的原始对象将被销毁。所以,为 ClassB 类添加 name 属性和 sayName() 方法的代码如下:function ClassB() {}ClassB.prototype = new ClassA();ClassB.prototype.name = "";ClassB.prototype.sayName = function () {alert(this.name);};可通过运行下面的例子测试这段代码:var objA = new ClassA();var objB = new ClassB();objA.color = "blue";objB.color = "red";objB.name = "John";objA.sayColor();objB.sayColor();objB.sayName();TIY此外,在原型链中,instanceof 运算符的运行方式也很独特。对 ClassB 的所有实例,instanceof 为 ClassA 和 ClassB 都返回 true。例如:var objB = new ClassB();alert(objB instanceof ClassA);//输出 "true"alert(objB instanceof ClassB);//输出 "true"在 ECMAScript 的弱类型世界中,这是极其有用的工具,不过使用对象冒充时不能使用它。原型链的弊端是不支持多重继承。记住,原型链会用另一类型的对象重写类的 prototype 属性。混合方式这种继承方式使用构造函数定义类,并非使用任何原型。对象冒充的主要问题是必须使用构造函数方式,这不是最好的选择。不过如果使用原型链,就无法使用带参数的构造函数了。开发者如何选择呢?答案很简单,两者都用。在前一章,我们曾经讲解过创建类的最好方式是用构造函数定义属性,用原型定义方法。这种方式同样适用于继承机制,用对象冒充继承构造函数的属性,用原型链继承 prototype 对象的方法。用这两种方式重写前面的例子,代码如下:function ClassA(sColor) {this.color = sColor;}ClassA.prototype.sayColor = function () {alert(this.color);};function ClassB(sColor, sName) {`ClassA.call(this, sColor);`this.name = sName;}`ClassB.prototype = new ClassA();`ClassB.prototype.sayName = function () {alert(this.name);};在此例子中,继承机制由两行突出显示的蓝色代码实现。在第一行突出显示的代码中,在 ClassB 构造函数中,用对象冒充继承 ClassA 类的 sColor 属性。在第二行突出显示的代码中,用原型链继承 ClassA 类的方法。由于这种混合方式使用了原型链,所以 instanceof 运算符仍能正确运行。下面的例子测试了这段代码:var objA = new ClassA("blue");var objB = new ClassB("red", "John");objA.sayColor();//输出 "blue"objB.sayColor();//输出 "red"objB.sayName();//输出 "John"TIY
标签:

js ECMAScript 类型转换js代码

ECMAScript 类型转换 所有程序设计语言最重要的特征之一是具有进行类型转换的能力。 ECMAScript 给开发者提供了大量简单的类型转换方法。 大部分类型具有进行简单转换的方法,还有ECMAScript 类型转换所有程序设计语言最重要的特征之一是具有进行类型转换的能力。ECMAScript 给开发者提供了大量简单的类型转换方法。大部分类型具有进行简单转换的方法,还有几个全局方法可以用于更复杂的转换。无论哪种情况,在 ECMAScript 中,类型转换都是简短的一步操作。转换成字符串ECMAScript 的 Boolean 值、数字和字符串的原始值的有趣之处在于它们是伪对象,这意味着它们实际上具有属性和方法。例如,要获得字符串的长度,可以采用下面的代码:var sColor = "red";alert(sColor.length);//输出 "3"尽管 "red" 是原始类型的字符串,它仍然具有属性 length,用于存放字符串的大小。总而言之,3 种主要的原始类型 Boolean 值、数字和字符串都有 toString() 方法,可以把它们的值转换成字符串。提示:您也许会问,“字符串还有 toString() 方法吗,这不是多余吗?”是的,的确如此,不过 ECMAScript 定义所有对象都有 toString() 方法,无论它是伪对象,还是真对象。因为 String 类型属于伪对象,所以它一定有 toString() 方法。Boolean 类型的 toString() 方法只是输出 "true" 或 "false",结果由变量的值决定:var bFound = false;alert(bFound.toString());//输出 "false"Number 类型的 toString() 方法比较特殊,它有两种模式,即默认模式和基模式。采用默认模式,toString() 方法只是用相应的字符串输出数字值(无论是整数、浮点数还是科学计数法),如下所示:var iNum1 = 10;var iNum2 = 10.0;alert(iNum1.toString());//输出 "10"alert(iNum2.toString());//输出 "10"注释:在默认模式中,无论最初采用什么表示法声明数字,Number 类型的 toString() 方法返回的都是数字的十进制表示。因此,以八进制或十六进制字面量形式声明的数字输出的都是十进制形式的。采用 Number 类型的 toString() 方法的基模式,可以用不同的基输出数字,例如二进制的基是 2,八进制的基是 8,十六进制的基是 16。基只是要转换成的基数的另一种加法而已,它是 toString() 方法的参数:var iNum = 10;alert(iNum.toString(2));//输出 "1010"alert(iNum.toString(8));//输出 "12"alert(iNum.toString(16));//输出 "A"在前面的示例中,以 3 种不同的形式输出了数字 10,即二进制形式、八进制形式和十六进制形式。HTML 采用十六进制表示每种颜色,在 HTML 中处理数字时这种功能非常有用。注释:对数字调用 toString(10) 与调用 toString() 相同,它们返回的都是该数字的十进制形式。参阅:请参阅 JavaScript 参考手册提供的有关 toString() 方法的详细信息:arrayObject.toString()booleanObject.toString()dateObject.toString()NumberObject.toString()stringObject.toString()转换成数字ECMAScript 提供了两种把非数字的原始值转换成数字的方法,即 parseInt() 和 parseFloat()。正如您可能想到的,前者把值转换成整数,后者把值转换成浮点数。只有对 String 类型调用这些方法,它们才能正确运行;对其他类型返回的都是 NaN。parseInt()在判断字符串是否是数字值前,parseInt() 和 parseFloat() 都会仔细分析该字符串。parseInt() 方法首先查看位置 0 处的字符,判断它是否是个有效数字;如果不是,该方法将返回 NaN,不再继续执行其他操作。但如果该字符是有效数字,该方法将查看位置 1 处的字符,进行同样的测试。这一过程将持续到发现非有效数字的字符为止,此时 parseInt() 将把该字符之前的字符串转换成数字。例如,如果要把字符串 "12345red" 转换成整数,那么 parseInt() 将返回 12345,因为当它检查到字符 r 时,就会停止检测过程。字符串中包含的数字字面量会被正确转换为数字,比如 "0xA" 会被正确转换为数字 10。不过,字符串 "22.5" 将被转换成 22,因为对于整数来说,小数点是无效字符。一些示例如下:var iNum1 = parseInt("12345red");//返回 12345var iNum1 = parseInt("0xA");//返回 10var iNum1 = parseInt("56.9");//返回 56var iNum1 = parseInt("red");//返回 NaNparseInt() 方法还有基模式,可以把二进制、八进制、十六进制或其他任何进制的字符串转换成整数。基是由 parseInt() 方法的第二个参数指定的,所以要解析十六进制的值,需如下调用 parseInt() 方法:var iNum1 = parseInt("AF", 16);//返回 175当然,对二进制、八进制甚至十进制(默认模式),都可以这样调用 parseInt() 方法:var iNum1 = parseInt("10", 2);//返回 2var iNum2 = parseInt("10", 8);//返回 8var iNum3 = parseInt("10", 10);//返回 10如果十进制数包含前导 0,那么最好采用基数 10,这样才不会意外地得到八进制的值。例如:var iNum1 = parseInt("010");//返回 8var iNum2 = parseInt("010", 8);//返回 8var iNum3 = parseInt("010", 10);//返回 10在这段代码中,两行代码都把字符 "010" 解析成一个数字。第一行代码把这个字符串看作八进制的值,解析它的方式与第二行代码(声明基数为 8)相同。最后一行代码声明基数为 10,所以 iNum3 最后等于 10。参阅请参阅 JavaScript 参考手册提供的有关 parseInt() 方法的详细信息:parseInt()。parseFloat()parseFloat() 方法与 parseInt() 方法的处理方式相似,从位置 0 开始查看每个字符,直到找到第一个非有效的字符为止,然后把该字符之前的字符串转换成整数。不过,对于这个方法来说,第一个出现的小数点是有效字符。如果有两个小数点,第二个小数点将被看作无效的。parseFloat() 会把这个小数点之前的字符转换成数字。这意味着字符串 "11.22.33" 将被解析成 11.22。使用 parseFloat() 方法的另一不同之处在于,字符串必须以十进制形式表示浮点数,而不是用八进制或十六进制。该方法会忽略前导 0,所以八进制数 0102 将被解析为 102。对于十六进制数 0xA,该方法将返回 NaN,因为在浮点数中,x 不是有效字符。(注释:经测试,具体的浏览器实现会返回 0,而不是 NaN。)此外,parseFloat() 方法也没有基模式。下面是使用 parseFloat() 方法的一些示例:var fNum1 = parseFloat("12345red");//返回 12345var fNum2 = parseFloat("0xA");//返回 NaNvar fNum3 = parseFloat("11.2");//返回 11.2var fNum4 = parseFloat("11.22.33");//返回 11.22var fNum5 = parseFloat("0102");//返回 102var fNum1 = parseFloat("red");//返回 NaN参阅请参阅 JavaScript 参考手册提供的有关 parseFloat() 方法的详细信息:parseFloat()。强制类型转换您还可以使用强制类型转换(type casting)来处理转换值的类型。使用强制类型转换可以访问特定的值,即使它是另一种类型的。编者注:cast 有“铸造”之意,很贴合“强制转换”的意思。ECMAScript 中可用的 3 种强制类型转换如下:Boolean(value) - 把给定的值转换成 Boolean 型;Number(value) - 把给定的值转换成数字(可以是整数或浮点数);String(value) - 把给定的值转换成字符串;用这三个函数之一转换值,将创建一个新值,存放由原始值直接转换成的值。这会造成意想不到的后果。Boolean() 函数当要转换的值是至少有一个字符的字符串、非 0 数字或对象时,Boolean() 函数将返回 true。如果该值是空字符串、数字 0、undefined 或 null,它将返回 false。可以用下面的代码测试 Boolean 型的强制类型转换:var b1 = Boolean("");//false - 空字符串var b2 = Boolean("hello");//true - 非空字符串var b1 = Boolean(50);//true - 非零数字var b1 = Boolean(null);//false - nullvar b1 = Boolean(0);//false - 零var b1 = Boolean(new object());//true - 对象Number() 函数Number() 函数的强制类型转换与 parseInt() 和 parseFloat() 方法的处理方式相似,只是它转换的是整个值,而不是部分值。还记得吗,parseInt() 和 parseFloat() 方法只转换第一个无效字符之前的字符串,因此 "1.2.3" 将分别被转换为 "1" 和 "1.2"。用 Number() 进行强制类型转换,"1.2.3" 将返回 NaN,因为整个字符串值不能转换成数字。如果字符串值能被完整地转换,Number() 将判断是调用 parseInt() 方法还是 parseFloat() 方法。下表说明了对不同的值调用 Number() 方法会发生的情况:用法结果Number(false)0Number(true)1Number(undefined)NaNNumber(null)0Number("1.2")1.2Number("12")12Number("1.2.3")NaNNumber(new object())NaNNumber(50)50String() 函数最后一种强制类型转换方法 String() 是最简单的,因为它可把任何值转换成字符串。要执行这种强制类型转换,只需要调用作为参数传递进来的值的 toString() 方法,即把 12 转换成 "12",把 true 转换成 "true",把 false 转换成 "false",以此类推。强制转换成字符串和调用 toString() 方法的唯一不同之处在于,对 null 和 undefined 值强制类型转换可以生成字符串而不引发错误:var s1 = String(null);//"null"var oNull = null;var s2 = oNull.toString();//会引发错误在处理 ECMAScript 这样的弱类型语言时,强制类型转换非常有用,不过应该确保使用值的正确。
标签:

js HTML DOM - 事件js代码

HTML DOM - 事件 HTML DOM 允许 JavaScript 对 HTML 事件作出反应。。 实例HTML DOM - 事件HTML DOM 允许 JavaScript 对 HTML 事件作出反应。。实例<div style="background-color:#8AB83D;width:160px;height:60px;margin:20px;padding-top:20px;color:#ffffff;font-weight:bold;font-size:14px;float:left;text-align:center;" onmouseover="this.innerHTML='Thank You'" onmouseout="this.innerHTML='Mouse Over Me'">Mouse Over Me</div><div style="background-color:#8AB83D;width:160px;height:60px;margin:20px;padding-top:20px;color:#ffffff;font-weight:bold;font-size:14px;float:left;text-align:center;" onclick="clickMeEvent(this)">Click Me</div><script type="application/javascript"><!--function clickMeEvent(obj){if (obj.innerHTML=="Goodbye"){obj.style.display="none";}else if (obj.innerHTML=="Thank You"){obj.innerHTML="Goodbye";}else if (obj.innerHTML=="Click Me<br>Click Me Again<br>And Again"){obj.innerHTML="Thank You";}else if (obj.innerHTML=="Click Me<br>Click Me Again"){obj.innerHTML=obj.innerHTML+"<br>And Again";}else{obj.innerHTML=obj.innerHTML+"<br>Click Me Again";}}//--></script>对事件作出反应当事件发生时,可以执行 JavaScript,比如当用户点击一个 HTML 元素时。如需在用户点击某个元素时执行代码,请把 JavaScript 代码添加到 HTML 事件属性中:onclick=_JavaScript_HTML 事件的例子:当用户点击鼠标时当网页已加载时当图片已加载时当鼠标移动到元素上时当输入字段被改变时当 HTML 表单被提交时当用户触发按键时在本例中,当用户点击时,会改变 <h1> 元素的内容:实例<!DOCTYPE html><html><body><h1 onclick="this.innerHTML='hello!'">请点击这段文本!</h1></body></html>在本例中,会从事件处理程序中调用函数:实例<!DOCTYPE html><html><head><script>function changetext(id){id.innerHTML="hello!";}</script></head><body><h1 onclick="changetext(this)">请点击这段文本!</h1></body></html>HTML 事件属性如需向 HTML 元素分配事件,您可以使用事件属性。实例向 button 元素分配一个 onclick 事件:<button onclick="displayDate()">试一试</button>在上面的例子中,当点击按钮时,会执行名为 displayDate 的函数。使用 HTML DOM 来分配事件HTML DOM 允许您使用 JavaScript 向 HTML 元素分配事件:实例为 button 元素分配 onclick 事件:<script>document.getElementById("myBtn").onclick=function(){displayDate()};</script>在上面的例子中,名为 displayDate 的函数被分配给了 id=myButn" 的 HTML 元素。当按钮被点击时,将执行函数。onload 和 onunload 事件当用户进入或离开页面时,会触发 onload 和 onunload 事件。onload 事件可用于检查访客的浏览器类型和版本,以便基于这些信息来加载不同版本的网页。onload 和 onunload 事件可用于处理 cookies。实例<body onload="checkCookies()">onchange 事件onchange 事件常用于输入字段的验证。下面的例子展示了如何使用 onchange。当用户改变输入字段的内容时,将调用 upperCase() 函数。实例<input type="text" id="fname" onchange="upperCase()">onmouseover 和 onmouseout 事件onmouseover 和 onmouseout 事件可用于在鼠标指针移动到或离开元素时触发函数。实例一个简单的 onmouseover-onmouseout 例子:<div style="background-color:#8AB83D;width:150px;height:60px;margin:20px;padding-top:20px;color:#ffffff;font-weight:bold;font-size:18px;text-align:center;" onmouseover="this.innerHTML='谢谢'" onmouseout="this.innerHTML='把鼠标移上来'">把鼠标移上来</div><p class="tiy"><a target="_blank" href="/tiy/t.asp?f=dom_event_onmouseover">亲自试一试</a></p></div>onmousedown、onmouseup 以及 onclick 事件onmousedown、onmouseup 以及 onclick 事件是鼠标点击的全部过程。首先当某个鼠标按钮被点击时,触发 onmousedown 事件,然后,当鼠标按钮被松开时,会触发 onmouseup 事件,最后,当鼠标点击完成时,触发 onclick 事件。实例一个简单的 onmousedown-onmouseup 实例:<div onmousedown="mDown(this)" onmouseup="mUp(this)" style="background-color:#8AB83D;width:150px;height:60px;margin:20px;padding-top:20px;color:#ffffff;font-weight:bold;font-size:18px;text-align:center;">点击这里</div><script type="application/javascript"><!--function mDown(obj){obj.style.backgroundColor="#1ec5e5";obj.innerHTML="松开鼠标"}function mUp(obj){obj.style.backgroundColor="#8AB83D";obj.innerHTML="谢谢"}//--></script>HTML DOM 事件对象参考手册如需每个事件的完整描述和例子,请访问我们的 HTML DOM 参考手册。
标签:

js ECMAScript 原始类型js代码

ECMAScript 原始类型 ECMAScript 有 5 种原始类型(primitive type),即 Undefined、Null、Boolean、Number 和 String。 tECMAScript 原始类型ECMAScript 有 5 种原始类型(primitive type),即 Undefined、Null、Boolean、Number 和 String。typeof 运算符typeof 运算符有一个参数,即要检查的变量或值。例如:var sTemp = "test string";alert (typeof sTemp);//输出 "string"alert (typeof 86);//输出 "number"对变量或值调用 typeof 运算符将返回下列值之一:undefined - 如果变量是 Undefined 类型的boolean - 如果变量是 Boolean 类型的number - 如果变量是 Number 类型的string - 如果变量是 String 类型的object - 如果变量是一种引用类型或 Null 类型的注释:您也许会问,为什么 typeof 运算符对于 null 值会返回 "Object"。这实际上是 JavaScript 最初实现中的一个错误,然后被 ECMAScript 沿用了。现在,null 被认为是对象的占位符,从而解释了这一矛盾,但从技术上来说,它仍然是原始值。Undefined 类型如前所述,Undefined 类型只有一个值,即 undefined。当声明的变量未初始化时,该变量的默认值是 undefined。var oTemp;前面一行代码声明变量 oTemp,没有初始值。该变量将被赋予值 undefined,即 undefined 类型的字面量。可以用下面的代码段测试该变量的值是否等于 undefined:var oTemp;alert(oTemp == undefined);这段代码将显示 "true",说明这两个值确实相等。还可以用 typeof 运算符显示该变量的值是 undefined:var oTemp;alert(typeof oTemp); //输出 "undefined"提示:值 undefined 并不同于未定义的值。但是,typeof 运算符并不真正区分这两种值。考虑下面的代码:var oTemp;alert(typeof oTemp);//输出 "undefined"alert(typeof oTemp2);//输出 "undefined"前面的代码对两个变量输出的都是 "undefined",即使只有变量 oTemp2 从未被声明过。如果对 oTemp2 使用除 typeof 之外的其他运算符的话,会引起错误,因为其他运算符只能用于已声明的变量上。例如,下面的代码将引发错误:var oTemp;alert(oTemp2 == undefined);当函数无明确返回值时,返回的也是值 "undefined",如下所示:function testFunc() {}alert(testFunc() == undefined);//输出 "true"Null 类型另一种只有一个值的类型是 Null,它只有一个专用值 null,即它的字面量。值 undefined 实际上是从值 null 派生来的,因此 ECMAScript 把它们定义为相等的。alert(null == undefined);//输出 "true"尽管这两个值相等,但它们的含义不同。undefined 是声明了变量但未对其初始化时赋予该变量的值,null 则用于表示尚未存在的对象(在讨论 typeof 运算符时,简单地介绍过这一点)。如果函数或方法要返回的是对象,那么找不到该对象时,返回的通常是 null。Boolean 类型Boolean 类型是 ECMAScript 中最常用的类型之一。它有两个值 true 和 false (即两个 Boolean 字面量)。即使 false 不等于 0,0 也可以在必要时被转换成 false,这样在 Boolean 语句中使用两者都是安全的。var bFound = true;var bLost = false;Number 类型ECMA-262 中定义的最特殊的类型是 Number 类型。这种类型既可以表示 32 位的整数,还可以表示 64 位的浮点数。直接输入的(而不是从另一个变量访问的)任何数字都被看做 Number 类型的字面量。例如,下面的代码声明了存放整数值的变量,它的值由字面量 86 定义:var iNum = 86;八进制数和十六进制数整数也可以被表示为八进制(以 8 为底)或十六进制(以 16 为底)的字面量。八进制字面量的首数字必须是 0,其后的数字可以是任何八进制数字(0-7),如下面的代码所示:var iNum = 070;//070 等于十进制的 56要创建十六进制的字面量,首位数字必须为 0,后面接字母 x,然后是任意的十六进制数字(0 到 9 和 A 到 F)。这些字母可以是大写的,也可以是小写的。例如:var iNum = 0x1f;//0x1f 等于十进制的 31var iNum = 0xAB;//0xAB 等于十进制的 171提示:尽管所有整数都可以表示为八进制或十六进制的字面量,但所有数学运算返回的都是十进制结果。浮点数要定义浮点值,必须包括小数点和小数点后的一位数字(例如,用 1.0 而不是 1)。这被看作浮点数字面量。例如:var fNum = 5.0;对于浮点字面量的有趣之处在于,用它进行计算前,真正存储的是字符串。科学计数法对于非常大或非常小的数,可以用科学计数法表示浮点数,可以把一个数表示为数字(包括十进制数字)加 e(或 E),后面加乘以 10 的倍数。例如:var fNum = 5.618e7该符号表示的是数 56180000。把科学计数法转化成计算式就可以得到该值:5.618 x 10<sup>7</sup>。也可以用科学计数法表示非常小的数,例如 0.00000000000000008 可以表示为 8-e<sup>17</sup>(这里,10 被升到 -17 次冥,意味着需要被 10 除 17 次)。ECMAScript 默认把具有 6 个或 6 个以上前导 0 的浮点数转换成科学计数法。提示:也可用 64 位 IEEE 754 形式存储浮点值,这意味着十进制值最多可以有 17 个十进制位。17 位之后的值将被裁去,从而造成一些小的数学误差。特殊的 Number 值几个特殊值也被定义为 Number 类型。前两个是 Number.MAX_VALUE 和 Number.MIN_VALUE,它们定义了 Number 值集合的外边界。所有 ECMAScript 数都必须在这两个值之间。不过计算生成的数值结果可以不落在这两个值之间。当计算生成的数大于 Number.MAX_VALUE 时,它将被赋予值 Number.POSITIVE_INFINITY,意味着不再有数字值。同样,生成的数值小于 Number.MIN_VALUE 的计算也会被赋予值 Number.NEGATIVE_INFINITY,也意味着不再有数字值。如果计算返回的是无穷大值,那么生成的结果不能再用于其他计算。事实上,有专门的值表示无穷大,(如你猜到的)即 Infinity。Number.POSITIVE_INFINITY 的值为 Infinity。Number.NEGATIVE_INFINITY 的值为 -Infinity。由于无穷大数可以是正数也可以是负数,所以可用一个方法判断一个数是否是有穷的(而不是单独测试每个无穷数)。可以对任何数调用 isFinite() 方法,以确保该数不是无穷大。例如:var iResult = iNum * some_really_large_number;`if (isFinite(iResult))` {alert("finite");}else {alert("infinite");}最后一个特殊值是 NaN,表示非数(Not a Number)。NaN 是个奇怪的特殊值。一般说来,这种情况发生在类型(String、Boolean 等)转换失败时。例如,要把单词 blue 转换成数值就会失败,因为没有与之等价的数值。与无穷大一样,NaN 也不能用于算术计算。NaN 的另一个奇特之处在于,它与自身不相等,这意味着下面的代码将返回 false:alert(NaN == NaN);//输出 "false"出于这个原因,不推荐使用 NaN 值本身。函数 isNaN() 会做得相当好:alert(isNaN("blue"));//输出 "true"alert(isNaN("666"));//输出 "false"String 类型String 类型的独特之处在于,它是唯一没有固定大小的原始类型。可以用字符串存储 0 或更多的 Unicode 字符,有 16 位整数表示(Unicode 是一种国际字符集,本教程后面将讨论它)。字符串中每个字符都有特定的位置,首字符从位置 0 开始,第二个字符在位置 1,依此类推。这意味着字符串中的最后一个字符的位置一定是字符串的长度减 1:字符串字面量是由双引号(")或单引号(')声明的。而 Java 则是用双引号声明字符串,用单引号声明字符。但是由于 ECMAScript 没有字符类型,所以可使用这两种表示法中的任何一种。例如,下面的两行代码都有效:var sColor1 = "red";var sColor2 = 'red';String 类型还包括几种字符字面量,Java、C 和 Perl 的开发者应该对此非常熟悉。下面列出了 ECMAScript 的字符字面量:字面量含义\n换行\t制表符\b空格\r回车\f换页符\反斜杠\'单引号\"双引号\0nnn八进制代码 nnn 表示的字符(n 是 0 到 7 中的一个八进制数字)\xnn十六进制代码 nn 表示的字符(n 是 0 到 F 中的一个十六进制数字)\unnnn十六进制代码 nnnn 表示的 Unicode 字符(n 是 0 到 F 中的一个十六进制数字)
标签:

js HTML DOM - 元素js代码

HTML DOM - 元素 添加、删除和替换 HTML 元素。 创建新的 HTML 元素 - appendChild() 如需向 HTML DOM 添加新元素,您首先必须创建该元素,然后把它追HTML DOM - 元素添加、删除和替换 HTML 元素。创建新的 HTML 元素 - appendChild()如需向 HTML DOM 添加新元素,您首先必须创建该元素,然后把它追加到已有的元素上。实例<div id="div1"><p id="p1">This is a paragraph.</p><p id="p2">This is another paragraph.</p></div><script>var para=document.createElement("p");var node=document.createTextNode("This is new.");para.appendChild(node);var element=document.getElementById("div1");element.appendChild(para);</script>例子解释这段代码创建了一个新的 <p> 元素:var para=document.createElement("p");如需向 <p> 元素添加文本,您首先必须创建文本节点。这段代码创建文本节点:var node=document.createTextNode("This is a new paragraph.");然后您必须向 <p> 元素追加文本节点:para.appendChild(node);最后,您必须向已有元素追加这个新元素。这段代码查找到一个已有的元素:var element=document.getElementById("div1");这段代码向这个已存在的元素追加新元素:element.appendChild(para);创建新的 HTML 元素 - insertBefore()上一个例子中的 appendChild() 方法,将新元素作为父元素的最后一个子元素进行添加。如果不希望如此,您可以使用 insertBefore() 方法:实例<div id="div1"><p id="p1">This is a paragraph.</p><p id="p2">This is another paragraph.</p></div><script>var para=document.createElement("p");var node=document.createTextNode("This is new.");para.appendChild(node);var element=document.getElementById("div1");var child=document.getElementById("p1");element.insertBefore(para,child);</script>删除已有的 HTML 元素如需删除 HTML 元素,您必须清楚该元素的父元素:实例<div id="div1"><p id="p1">This is a paragraph.</p><p id="p2">This is another paragraph.</p></div><script>var parent=document.getElementById("div1");var child=document.getElementById("p1");parent.removeChild(child);</script>例子解释这个 HTML 文档包含一个带有两个子节点(两个 <p> 元素)的 <div> 元素:<div id="div1"><p id="p1">This is a paragraph.</p><p id="p2">This is another paragraph.</p></div>查找 id="div1" 的元素:var parent=document.getElementById("div1");查找 id="p1" 的 <p> 元素:var child=document.getElementById("p1");从父元素中删除子元素:parent.removeChild(child);提示:能否在不引用父元素的情况下删除某个元素?很抱歉。DOM 需要了解您需要删除的元素,以及它的父元素。这里提供一个常用的解决方法:找到您需要删除的子元素,然后使用 parentNode 属性来查找其父元素:var child=document.getElementById("p1");child.parentNode.removeChild(child);替换 HTML 元素如需替换 HTML DOM 中的元素,请使用 replaceChild() 方法:实例<div id="div1"><p id="p1">This is a paragraph.</p><p id="p2">This is another paragraph.</p></div><script>var para=document.createElement("p");var node=document.createTextNode("This is new.");para.appendChild(node);var parent=document.getElementById("div1");var child=document.getElementById("p1");parent.replaceChild(para,child);</script>
标签:

js AJAX - 向服务器发送请求js代码

AJAX - 向服务器发送请求XHR 创建对象 XHR 响应XMLHttpRequest 对象用于和服务器交换数据。 向服务器发送请求 如需将请求发送到服务器,我们使用 XMLAJAX - 向服务器发送请求XHR 创建对象XHR 响应XMLHttpRequest 对象用于和服务器交换数据。向服务器发送请求如需将请求发送到服务器,我们使用 XMLHttpRequest 对象的 open() 和 send() 方法:xmlhttp.open("GET","test1.txt",true);xmlhttp.send();方法描述open(method,url,async)规定请求的类型、URL 以及是否异步处理请求。method:请求的类型;GET 或 POSTurl:文件在服务器上的位置async:true(异步)或 false(同步)send(string)将请求发送到服务器。string:仅用于 POST 请求GET 还是 POST?与 POST 相比,GET 更简单也更快,并且在大部分情况下都能用。然而,在以下情况中,请使用 POST 请求:无法使用缓存文件(更新服务器上的文件或数据库)向服务器发送大量数据(POST 没有数据量限制)发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠GET 请求一个简单的 GET 请求:xmlhttp.open("GET","demo_get.asp",true);xmlhttp.send();在上面的例子中,您可能得到的是缓存的结果。为了避免这种情况,请向 URL 添加一个唯一的 ID:xmlhttp.open("GET","demo_get.asp?t=" + `Math.random()`,true);xmlhttp.send();如果您希望通过 GET 方法发送信息,请向 URL 添加信息:xmlhttp.open("GET","demo_get2.asp?fname=Bill&lname=Gates",true);xmlhttp.send();POST 请求一个简单 POST 请求:xmlhttp.open("POST","demo_post.asp",true);xmlhttp.send();如果需要像 HTML 表单那样 POST 数据,请使用 setRequestHeader() 来添加 HTTP 头。然后在 send() 方法中规定您希望发送的数据:xmlhttp.open("POST","ajax_test.asp",true);xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");xmlhttp.send("fname=Bill&lname=Gates");方法描述setRequestHeader(header,value)向请求添加 HTTP 头。header: 规定头的名称value: 规定头的值url - 服务器上的文件open() 方法的 url 参数是服务器上文件的地址:xmlhttp.open("GET","ajax_test.asp",true);该文件可以是任何类型的文件,比如 .txt 和 .xml,或者服务器脚本文件,比如 .asp 和 .php (在传回响应之前,能够在服务器上执行任务)。异步 - True 或 False?AJAX 指的是异步 JavaScript 和 XML(Asynchronous JavaScript and XML)。XMLHttpRequest 对象如果要用于 AJAX 的话,其 open() 方法的 async 参数必须设置为 true:xmlhttp.open("GET","ajax_test.asp",`true`);对于 web 开发人员来说,发送异步请求是一个巨大的进步。很多在服务器执行的任务都相当费时。AJAX 出现之前,这可能会引起应用程序挂起或停止。通过 AJAX,JavaScript 无需等待服务器的响应,而是:在等待服务器响应时执行其他脚本当响应就绪后对响应进行处理Async = true当使用 async=true 时,请规定在响应处于 onreadystatechange 事件中的就绪状态时执行的函数:xmlhttp.onreadystatechange=function(){if (xmlhttp.readyState==4 && xmlhttp.status==200){document.getElementById("myDiv").innerHTML=xmlhttp.responseText;}}xmlhttp.open("GET","test1.txt",true);xmlhttp.send();您将在稍后的章节学习更多有关 onreadystatechange 的内容。Async = false如需使用 async=false,请将 open() 方法中的第三个参数改为 false:xmlhttp.open("GET","test1.txt",false);我们不推荐使用 async=false,但是对于一些小型的请求,也是可以的。请记住,JavaScript 会等到服务器响应就绪才继续执行。如果服务器繁忙或缓慢,应用程序会挂起或停止。注释:当您使用 async=false 时,请不要编写 onreadystatechange 函数 - 把代码放到 send() 语句后面即可:xmlhttp.open("GET","test1.txt",false);xmlhttp.send();document.getElementById("myDiv").innerHTML=xmlhttp.responseText;XHR 创建对象XHR 响应
标签:

js HTML DOM - 导航js代码

HTML DOM - 导航 通过 HTML DOM,您能够使用节点关系在节点树中导航。 HTML DOM 节点列表 getElementsByTagName() 方法返回节点列表。节点列表是一HTML DOM - 导航通过 HTML DOM,您能够使用节点关系在节点树中导航。HTML DOM 节点列表getElementsByTagName() 方法返回节点列表。节点列表是一个节点数组。下面的代码选取文档中的所有 <p> 节点:实例var x=document.getElementsByTagName("p");可以通过下标号访问这些节点。如需访问第二个 <p>,您可以这么写:y=x[1];注释:下标号从 0 开始。HTML DOM 节点列表长度length 属性定义节点列表中节点的数量。您可以使用 length 属性来循环节点列表:实例x=document.getElementsByTagName("p");for (i=0;i<x.length;i++){document.write(x[i].innerHTML);document.write("<br />");}例子解释:获取所有 <p> 元素节点输出每个 <p> 元素的文本节点的值导航节点关系您能够使用三个节点属性:parentNode、firstChild 以及 lastChild ,在文档结构中进行导航。请看下面的 HTML 片段:<html><body><p>Hello World!</p><div><p>DOM 很有用!</p><p>本例演示节点关系。</p></div></body></html>首个 <p> 元素是 <body> 元素的首个子元素(firstChild)<div> 元素是 <body> 元素的最后一个子元素(lastChild)<body> 元素是首个 <p> 元素和 <div> 元素的父节点(parentNode)firstChild 属性可用于访问元素的文本:实例<html><body><p id="intro">Hello World!</p><script>x=document.getElementById("intro");document.write(x.firstChild.nodeValue);</script></body></html>DOM 根节点这里有两个特殊的属性,可以访问全部文档:document.documentElement - 全部文档document.body - 文档的主体实例<html><body><p>Hello World!</p><div><p>DOM 很有用!</p><p>本例演示 <b>document.body</b> 属性。</p></div><script>alert(document.body.innerHTML);</script></body></html>childNodes 和 nodeValue除了 innerHTML 属性,您也可以使用 childNodes 和 nodeValue 属性来获取元素的内容。下面的代码获取 id="intro" 的 <p> 元素的值:实例<html><body><p id="intro">Hello World!</p><script>var txt=document.getElementById("intro").childNodes[0].nodeValue;document.write(txt);</script></body></html>在上面的例子中,getElementById 是一个方法,而 childNodes 和 nodeValue 是属性。在本教程中,我们将使用 innerHTML 属性。不过,学习上面的方法有助于对 DOM 树结构和导航的理解。
标签:

js ECMAScript 对象应用js代码

ECMAScript 对象应用 对象的创建和销毁都在 JavaScript 执行过程中发生,理解这种范式的含义对理解整个语言至关重要。 声明和实例化 对象的创建方式是用关键字 new 后面跟上ECMAScript 对象应用对象的创建和销毁都在 JavaScript 执行过程中发生,理解这种范式的含义对理解整个语言至关重要。声明和实例化对象的创建方式是用关键字 new 后面跟上实例化的类的名字:var oObject = new Object();var oStringObject = new String();第一行代码创建了 Object 类的一个实例,并把它存储到变量 oObject 中。第二行代码创建了 String 类的一个实例,把它存储在变量 oStringObject 中。如果构造函数无参数,括号则不是必需的。因此可以采用下面的形式重写上面的两行代码:var oObject = new Object;var oStringObject = new String;对象引用在前面的章节中,我们介绍了引用类型的概念。在 ECMAScript 中,不能访问对象的物理表示,只能访问对象的引用。每次创建对象,存储在变量中的都是该对象的引用,而不是对象本身。对象废除ECMAScript 拥有无用存储单元收集程序(garbage collection routine),意味着不必专门销毁对象来释放内存。当再没有对对象的引用时,称该对象被废除(dereference)了。运行无用存储单元收集程序时,所有废除的对象都被销毁。每当函数执行完它的代码,无用存储单元收集程序都会运行,释放所有的局部变量,还有在一些其他不可预知的情况下,无用存储单元收集程序也会运行。把对象的所有引用都设置为 null,可以强制性地废除对象。例如:var oObject = new Object;// do something with the object hereoObject = null;当变量 oObject 设置为 null 后,对第一个创建的对象的引用就不存在了。这意味着下次运行无用存储单元收集程序时,该对象将被销毁。每用完一个对象后,就将其废除,来释放内存,这是个好习惯。这样还确保不再使用已经不能访问的对象,从而防止程序设计错误的出现。此外,旧的浏览器(如 IE/MAC)没有全面的无用存储单元收集程序,所以在卸载页面时,对象可能不能被正确销毁。废除对象和它的所有特性是确保内存使用正确的最好方法。注意:废除对象的所有引用时要当心。如果一个对象有两个或更多引用,则要正确废除该对象,必须将其所有引用都设置为 null。早绑定和晚绑定所谓绑定(binding),即把对象的接口与对象实例结合在一起的方法。早绑定(early binding)是指在实例化对象之前定义它的属性和方法,这样编译器或解释程序就能够提前转换机器代码。在 Java 和 Visual Basic 这样的语言中,有了早绑定,就可以在开发环境中使用 IntelliSense(即给开发者提供对象中属性和方法列表的功能)。ECMAScript 不是强类型语言,所以不支持早绑定。另一方面,晚绑定(late binding)指的是编译器或解释程序在运行前,不知道对象的类型。使用晚绑定,无需检查对象的类型,只需检查对象是否支持属性和方法即可。ECMAScript 中的所有变量都采用晚绑定方法。这样就允许执行大量的对象操作,而无任何惩罚。
标签:

js ECMAScript 关系运算符js代码

ECMAScript 关系运算符 关系运算符执行的是比较运算。每个关系运算符都返回一个布尔值。 常规比较方式 关系运算符小于、大于、小于等于和大于等于执行的是两个数的比较运算,比较方式与算术比ECMAScript 关系运算符关系运算符执行的是比较运算。每个关系运算符都返回一个布尔值。常规比较方式关系运算符小于、大于、小于等于和大于等于执行的是两个数的比较运算,比较方式与算术比较运算相同。每个关系运算符都返回一个布尔值:var bResult1 = 2 > 1//truevar bResult2 = 2 < 1//false不过,对两个字符串应用关系运算符,它们的行为则不同。许多人认为小于表示“在字母顺序上靠前”,大于表示“在字母顺序上靠后”,但事实并非如此。对于字符串,第一个字符串中每个字符的代码都与会第二个字符串中对应位置的字符的代码进行数值比较。完成这种比较操作后,返回一个 Boolean 值。问题在于大写字母的代码都小于小写字母的代码,这意味这着可能会遇到下列情况:var bResult = "Blue" < "alpha";alert(bResult);//输出 true在上面的例子中,字符串 "Blue" 小于 "alpha",因为字母 B 的字符代码是 66,字母 a 的字符代码是 97。要强制性得到按照真正的字母顺序比较的结果,必须把两个数转换成相同的大小写形式(全大写或全小写的),然后再进行比较:var bResult = "Blue".toLowerCase() < "alpha".toLowerCase();alert(bResult);//输出 false把两个运算数都转换成小写,确保了正确识别出 "alpha" 在字母顺序上位于 "Blue" 之前。比较数字和字符串另一种棘手的状况发生在比较两个字符串形式的数字时,比如:var bResult = "25" < "3";alert(bResult);//输出 "true"上面这段代码比较的是字符串 "25" 和 "3"。两个运算数都是字符串,所以比较的是它们的字符代码("2" 的字符代码是 50,"3" 的字符代码是 51)。不过,如果把某个运算数该为数字,那么结果就有趣了:var bResult = "25" < 3;alert(bResult);//输出 "false"这里,字符串 "25" 将被转换成数字 25,然后与数字 3 进行比较,结果不出所料。无论何时比较一个数字和一个字符串,ECMAScript 都会把字符串转换成数字,然后按照数字顺序比较它们。不过,如果字符串不能转换成数字又该如何呢?考虑下面的例子:var bResult = "a" < 3;alert(bResult);你能预料到这段代码输出什么吗?字母 "a" 不能转换成有意义的数字。不过,如果对它调用 parseInt() 方法,返回的是 NaN。根据规则,任何包含 NaN 的关系运算符都要返回 false,因此这段代码也输出 false:var bResult = "a" >= 3;alert(bResult);通常,如果小于运算的两个值返回 false,那么大于等于运算必须返回 true,不过如果某个数字是 NaN,情况则非如此。
标签:

js ECMAScript 原始值和引用值js代码

ECMAScript 原始值和引用值 在 ECMAScript 中,变量可以存在两种类型的值,即原始值和引用值。 原始值和引用值 在 ECMAScript 中,变量可以存在两种类型的值,即原始ECMAScript 原始值和引用值在 ECMAScript 中,变量可以存在两种类型的值,即原始值和引用值。原始值和引用值在 ECMAScript 中,变量可以存在两种类型的值,即原始值和引用值。原始值存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问的位置。引用值存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存处。为变量赋值时,ECMAScript 的解释程序必须判断该值是原始类型,还是引用类型。要实现这一点,解释程序则需尝试判断该值是否为 ECMAScript 的原始类型之一,即 Undefined、Null、Boolean、Number 和 String 型。由于这些原始类型占据的空间是固定的,所以可将他们存储在较小的内存区域 - 栈中。这样存储便于迅速查寻变量的值。在许多语言中,字符串都被看作引用类型,而非原始类型,因为字符串的长度是可变的。ECMAScript 打破了这一传统。如果一个值是引用类型的,那么它的存储空间将从堆中分配。由于引用值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度。相反,放在变量的栈空间中的值是该对象存储在堆中的地址。地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响。如下图所示:原始类型如前所述,ECMAScript 有 5 种原始类型(primitive type),即 Undefined、Null、Boolean、Number 和 String。ECMA-262 把术语类型(type)定义为值的一个集合,每种原始类型定义了它包含的值的范围及其字面量表示形式。ECMAScript 提供了 typeof 运算符来判断一个值是否在某种类型的范围内。可以用这种运算符判断一个值是否表示一种原始类型:如果它是原始类型,还可以判断它表示哪种原始类型。在稍后的章节,我们将为您深入讲解 ECMAScript 的原始类型和引用类型。
标签:

js ECMAScript 等性运算符js代码

ECMAScript 等性运算符 判断两个变量是否相等是程序设计中非常重要的运算。在处理原始值时,这种运算相当简单,但涉及对象,任务就稍有点复杂。 ECMAScript 提供了两套等性运算符:ECMAScript 等性运算符判断两个变量是否相等是程序设计中非常重要的运算。在处理原始值时,这种运算相当简单,但涉及对象,任务就稍有点复杂。ECMAScript 提供了两套等性运算符:等号和非等号用于处理原始值,全等号和非全等号用于处理对象。等号和非等号在 ECMAScript 中,等号由双等号(==)表示,当且仅当两个运算数相等时,它返回 true。非等号由感叹号加等号(!=)表示,当且仅当两个运算数不相等时,它返回 true。为确定两个运算数是否相等,这两个运算符都会进行类型转换。执行类型转换的规则如下:如果一个运算数是 Boolean 值,在检查相等性之前,把它转换成数字值。false 转换成 0,true 为 1。如果一个运算数是字符串,另一个是数字,在检查相等性之前,要尝试把字符串转换成数字。如果一个运算数是对象,另一个是字符串,在检查相等性之前,要尝试把对象转换成字符串。如果一个运算数是对象,另一个是数字,在检查相等性之前,要尝试把对象转换成数字。在比较时,该运算符还遵守下列规则:值 null 和 undefined 相等。在检查相等性时,不能把 null 和 undefined 转换成其他值。如果某个运算数是 NaN,等号将返回 false,非等号将返回 true。如果两个运算数都是对象,那么比较的是它们的引用值。如果两个运算数指向同一对象,那么等号返回 true,否则两个运算数不等。重要提示:即使两个数都是 NaN,等号仍然返回 false,因为根据规则,NaN 不等于 NaN。下表列出了一些特殊情况,以及它们的结果:表达式值null == undefinedtrue"NaN" == NaNfalse5 == NaNfalseNaN == NaNfalseNaN != NaNtruefalse == 0truetrue == 1truetrue == 2falseundefined == 0falsenull == 0false"5" == 5true全等号和非全等号等号和非等号的同类运算符是全等号和非全等号。这两个运算符所做的与等号和非等号相同,只是它们在检查相等性前,不执行类型转换。全等号由三个等号表示(===),只有在无需类型转换运算数就相等的情况下,才返回 true。例如:var sNum = "66";var iNum = 66;alert(sNum == iNum);//输出 "true"alert(sNum === iNum);//输出 "false"在这段代码中,第一个 alert 使用等号来比较字符串 "66" 和数字 66,输出 "true"。如前所述,这是因为字符串 "66" 将被转换成数字 66,,然后才与另一个数字 66 进行比较。第二个 alert 使用全等号在没有类型转换的情况下比较字符串和数字,当然,字符串不等于数字,所以输出 "false"。非全等号由感叹号加两个等号(!==)表示,只有在无需类型转换运算数不相等的情况下,才返回 true。例如:var sNum = "66";var iNum = 66;alert(sNum != iNum);//输出 "false"alert(sNum !== iNum);//输出 "true"这里,第一个 alert 使用非等号,把字符串 "66" 转换成数字 66,使得它与第二个运算数 66 相等。因此,计算结果为 "false",因为两个运算数是相等的。第二个 alert 使用的非全等号。该运算是在问:"sNum" 与 "iNum" 不同吗?这个问题的答案是:是的(true),因为 sNum 是字符串,而 iNum 是数字,它们当然不同。
标签:

js HTML DOM 节点js代码

HTML DOM 节点 在 HTML DOM 中,所有事物都是节点。DOM 是被视为节点树的 HTML。 DOM 节点 根据 W3C 的 HTML DOM 标准,HTML 文档中的所有内容都是HTML DOM 节点在 HTML DOM 中,所有事物都是节点。DOM 是被视为节点树的 HTML。DOM 节点根据 W3C 的 HTML DOM 标准,HTML 文档中的所有内容都是节点:整个文档是一个文档节点每个 HTML 元素是元素节点HTML 元素内的文本是文本节点每个 HTML 属性是属性节点注释是注释节点HTML DOM 节点树HTML DOM 将 HTML 文档视作树结构。这种结构被称为节点树:HTML DOM Tree 实例通过 HTML DOM,树中的所有节点均可通过 JavaScript 进行访问。所有 HTML 元素(节点)均可被修改,也可以创建或删除节点。节点父、子和同胞节点树中的节点彼此拥有层级关系。父(parent)、子(child)和同胞(sibling)等术语用于描述这些关系。父节点拥有子节点。同级的子节点被称为同胞(兄弟或姐妹)。在节点树中,顶端节点被称为根(root)每个节点都有父节点、除了根(它没有父节点)一个节点可拥有任意数量的子同胞是拥有相同父节点的节点下面的图片展示了节点树的一部分,以及节点之间的关系:请看下面的 HTML 片段:<html><head><title>DOM 教程</title></head><body><h1>DOM 第一课</h1><p>Hello world!</p></body></html>从上面的 HTML 中:<html> 节点没有父节点;它是根节点<head> 和 <body> 的父节点是 <html> 节点文本节点 "Hello world!" 的父节点是 <p> 节点并且:<html> 节点拥有两个子节点:<head> 和 <body><head> 节点拥有一个子节点:<title> 节点<title> 节点也拥有一个子节点:文本节点 "DOM 教程"<h1> 和 <p> 节点是同胞节点,同时也是 <body> 的子节点并且:<head> 元素是 <html> 元素的首个子节点<body> 元素是 <html> 元素的最后一个子节点<h1> 元素是 <body> 元素的首个子节点<p> 元素是 <body> 元素的最后一个子节点警告!DOM 处理中的常见错误是希望元素节点包含文本。在本例中:<title>DOM 教程</title>,元素节点 <title>,包含值为 "DOM 教程" 的文本节点。可通过节点的 innerHTML 属性来访问文本节点的值。您将在稍后的章节中学习更多有关 innerHTML 属性的知识。
标签:

js ECMAScript Function 对象(类)js代码

ECMAScript Function 对象(类) ECMAScript 的函数实际上是功能完整的对象。 Function 对象(类) ECMAScript 最令人感兴趣的可能莫过于函数实际上ECMAScript Function 对象(类)ECMAScript 的函数实际上是功能完整的对象。Function 对象(类)ECMAScript 最令人感兴趣的可能莫过于函数实际上是功能完整的对象。Function 类可以表示开发者定义的任何函数。用 Function 类直接创建函数的语法如下:var function_name = new function(_arg1_, _arg2_, ..., _argN_, _function_body_)在上面的形式中,每个 arg 都是一个参数,最后一个参数是函数主体(要执行的代码)。这些参数必须是字符串。记得下面这个函数吗?function sayHi(sName, sMessage) {alert("Hello " + sName + sMessage);}还可以这样定义它:var sayHi = new Function("sName", "sMessage", "alert(\"Hello \" + sName + sMessage);");虽然由于字符串的关系,这种形式写起来有些困难,但有助于理解函数只不过是一种引用类型,它们的行为与用 Function 类明确创建的函数行为是相同的。请看下面这个例子:function doAdd(iNum) {alert(iNum + 20);}function doAdd(iNum) {alert(iNum + 10);}doAdd(10);//输出 "20"如你所知,第二个函数重载了第一个函数,使 doAdd(10) 输出了 "20",而不是 "30"。如果以下面的形式重写该代码块,这个概念就清楚了:var doAdd = new Function("iNum", "alert(iNum + 20)");var doAdd = new Function("iNum", "alert(iNum + 10)");doAdd(10);请观察这段代码,很显然,doAdd 的值被改成了指向不同对象的指针。函数名只是指向函数对象的引用值,行为就像其他对象一样。甚至可以使两个变量指向同一个函数:var doAdd = new Function("iNum", "alert(iNum + 10)");var alsodoAdd = doAdd;doAdd(10);//输出 "20"alsodoAdd(10);//输出 "20"在这里,变量 doAdd 被定义为函数,然后 alsodoAdd 被声明为指向同一个函数的指针。用这两个变量都可以执行该函数的代码,并输出相同的结果 - "20"。因此,如果函数名只是指向函数的变量,那么可以把函数作为参数传递给另一个函数吗?回答是肯定的!function callAnotherFunc(fnFunction, vArgument) {fnFunction(vArgument);}var doAdd = new Function("iNum", "alert(iNum + 10)");callAnotherFunc(doAdd, 10);//输出 "20"在上面的例子中,callAnotherFunc() 有两个参数 - 要调用的函数和传递给该函数的参数。这段代码把 doAdd() 传递给 callAnotherFunc() 函数,参数是 10,输出 "20"。注意:尽管可以使用 Function 构造函数创建函数,但最好不要使用它,因为用它定义函数比用传统方式要慢得多。不过,所有函数都应看作 Function 类的实例。Function 对象的 length 属性如前所述,函数属于引用类型,所以它们也有属性和方法。ECMAScript 定义的属性 length 声明了函数期望的参数个数。例如:function doAdd(iNum) {alert(iNum + 10);}function sayHi() {alert("Hi");}alert(doAdd.length);//输出 "1"alert(sayHi.length);//输出 "0"函数 doAdd() 定义了一个参数,因此它的 length 是 1;sayHi() 没有定义参数,所以 length 是 0。记住,无论定义了几个参数,ECMAScript 可以接受任意多个参数(最多 25 个),这一点在《函数概述》这一章中讲解过。属性 length 只是为查看默认情况下预期的参数个数提供了一种简便方式。Function 对象的方法Function 对象也有与所有对象共享的 valueOf() 方法和 toString() 方法。这两个方法返回的都是函数的源代码,在调试时尤其有用。例如:function doAdd(iNum) {alert(iNum + 10);}document.write(doAdd.toString());上面这段代码输出了 doAdd() 函数的文本。!
标签: