Javascript高级编程3

for-in 语句
for (sProp in window) {
  alert(sProp);
}
这里,for-in 语句用于显示 window 对象的所有属性。
前面讨论过的 PropertyIsEnumerable() 是 ECMAScript 中专门用于说明属性是否可以用 for-in 语句访问的方法。

有标签的语句
start : i = 5;
在这个例子中,标签 start 可以被之后的 break 或 continue 语句引用。

break 语句和 continue 语句都可以与有标签的语句联合使用,返回代码中的特定位置。

var iNum = 0;

outermost:
for (var i=0; i<10; i++) {
  for (var j=0; j<10; j++) {
    if (i == 5 && j == 5) {
    break outermost;
  }
  iNum++;
  }
}

alert(iNum); //输出 "55"
在上面的例子中,标签 outermost 表示的是第一个 for 语句。正常情况下,每个 for 语句执行 10 次代码块,这意味着 iNum++ 正常情况下将被执行 100 次,在执行完成时,iNum 应该等于 100。这里的 break 语句有一个参数,即停止循环后要跳转到的语句的标签。这样 break 语句不止能跳出内部 for 语句(即使用变量 j 的语句),还能跳出外部 for 语句(即使用变量 i 的语句)。因此,iNum 最后的值是 55,因为当 i 和 j 的值都等于 5 时,循环将终止。

可以以相同的方式使用 continue 语句:
var iNum = 0;

outermost:
for (var i=0; i<10; i++) {
  for (var j=0; j<10; j++) {
    if (i == 5 && j == 5) {
    continue outermost;
  }
  iNum++;
  }
}

alert(iNum); //输出 "95"
在上例中,continue 语句会迫使循环继续,不止是内部循环,外部循环也如此。当 j 等于 5 时出现这种情况,意味着内部循环将减少 5 次迭代,致使 iNum 的值为 95。
提示:可以看出,与 break 和 continue 联合使用的有标签语句非常强大,不过过度使用它们会给调试代码带来麻烦。要确保使用的标签具有说明性,同时不要嵌套太多层循环。

with 语句是运行缓慢的代码块,尤其是在已设置了属性值时。大多数情况下,如果可能,最好避免使用它。

ECMAScript 和 Java 中的 switch 语句有两点不同。在 ECMAScript 中,switch 语句可以用于字符串,而且能用不是常量的值说明情况:
var BLUE = "blue", RED = "red", GREEN  = "green";

switch (sColor) {
  case BLUE: alert("Blue");
    break;
  case RED: alert("Red");
    break;
  case GREEN: alert("Green");
    break;
  default: alert("Other");
}

函数的基本语法是这样的:
function functionName(arg0, arg1, ... argN) {
  statements
}

另一个重要概念是,与在 Java 中一样,函数在执行过 return 语句后立即停止代码。因此,return 语句后的代码都不会被执行。
例如,在下面的代码中,alert 窗口就不会显示出来:
function sum(iNum1, iNum2) {
  return iNum1 + iNum2;
  alert(iNum1 + iNum2);
}

注释:如果函数无明确的返回值,或调用了没有参数的 return 语句,那么它真正返回的值是 undefined。

在函数代码中,使用特殊对象 arguments,开发者无需明确指出参数名,就能访问它们。

与其他程序设计语言不同,ECMAScript 不会验证传递给函数的参数个数是否等于函数定义的参数个数。开发者定义的函数都可以接受任意个数的参数(根据 Netscape 的文档,最多可接受 255 个),而不会引发任何错误。任何遗漏的参数都会以 undefined 传递给函数,多余的函数将忽略。

ECMAScript 的函数实际上是功能完整的对象。
Function 对象(类)

ECMAScript 最令人感兴趣的可能莫过于函数实际上是功能完整的对象。
Function 类可以表示开发者定义的任何函数。
用 Function 类直接创建函数的语法如下:
var function_name = new function(arg1, arg2, ..., argN, function_body)
-------------------------------------------------------------------------
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 对象也有与所有对象共享的 valueOf() 方法和 toString() 方法。这两个方法返回的都是函数的源代码,在调试时尤其有用。例如:
function doAdd(iNum) {
  alert(iNum + 10);
}

document.write(doAdd.toString());
输出结果为:
function doAdd(iNum) { alert(iNum + 10); }

闭包,指的是词法表示包括不被计算的变量的函数,也就是说,函数可以使用函数之外定义的变量。

简单的闭包实例
在 ECMAScript 中使用全局变量是一个简单的闭包实例。

复杂的闭包实例
在一个函数中定义另一个会使闭包变得更加复杂。例如:
var iBaseNum = 10;

function addNum(iNum1, iNum2) {
  function doAdd() {
    return iNum1 + iNum2 + iBaseNum;
  }
  return doAdd();
}

ECMAScript 面向对象技术

面向对象术语
对象
ECMA-262 把对象(object)定义为“属性的无序集合,每个属性存放一个原始值、对象或函数”。严格来说,这意味着对象是无特定顺序的值的数组。
尽管 ECMAScript 如此定义对象,但它更通用的定义是基于代码的名词(人、地点或事物)的表示。


每个对象都由类定义,可以把类看做对象的配方。类不仅要定义对象的接口(interface)(开发者访问的属性和方法),还要定义对象的内部工作(使属性和方法发挥作用的代码)。编译器和解释程序都根据类的说明构建对象。

实例
程序使用类创建对象时,生成的对象叫作类的实例(instance)。对类生成的对象的个数的唯一限制来自于运行代码的机器的物理内存。每个实例的行为相同,但实例处理一组独立的数据。由类创建对象实例的过程叫做实例化(instantiation)。

一种面向对象语言需要向开发者提供四种基本能力:
封装 - 把相关的信息(无论数据或方法)存储在对象中的能力
聚集 - 把一个对象存储在另一个对象内的能力
继承 - 由另一个类(或多个类)得来类的属性和方法的能力
多态 - 编写能以多种方法运行的函数或方法的能力
ECMAScript 支持这些要求,因此可被是看做面向对象的。

对象的创建方式是用关键字 new 后面跟上实例化的类的名字:
var oObject = new Object();
var oStringObject = new String();
第一行代码创建了 Object 类的一个实例,并把它存储到变量 oObject 中。第二行代码创建了 String 类的一个实例,把它存储在变量 oStringObject 中。如果构造函数无参数,括号则不是必需的。因此可以采用下面的形式重写上面的两行代码:
var oObject = new Object;
var oStringObject = new String;

把对象的所有引用都设置为 null,可以强制性地废除对象。

早绑定和晚绑定
所谓绑定(binding),即把对象的接口与对象实例结合在一起的方法。
早绑定(early binding)是指在实例化对象之前定义它的属性和方法,这样编译器或解释程序就能够提前转换机器代码。ECMAScript 不是强类型语言,所以不支持早绑定。

另一方面,晚绑定(late binding)指的是编译器或解释程序在运行前,不知道对象的类型。使用晚绑定,无需检查对象的类型,只需检查对象是否支持属性和方法即可。ECMAScript 中的所有变量都采用晚绑定方法。这样就允许执行大量的对象操作,而无任何惩罚。

一般来说,可以创建并使用的对象有三种:本地对象、内置对象和宿主对象。

本地对象
ECMA-262 把本地对象(native object)定义为“独立于宿主环境的 ECMAScript 实现提供的对象”。简单来说,本地对象就是 ECMA-262 定义的类(引用类型)。它们包括:
Object
Function
Array
String
Boolean
Number
Date
RegExp
Error
EvalError
RangeError
ReferenceError
SyntaxError
TypeError
URIError

内置对象
ECMA-262 把内置对象(built-in object)定义为“由 ECMAScript 实现提供的、独立于宿主环境的所有对象,在 ECMAScript 程序开始执行时出现”。这意味着开发者不必明确实例化内置对象,它已被实例化了。ECMA-262 只定义了两个内置对象,即 Global 和 Math (它们也是本地对象,根据定义,每个内置对象都是本地对象)。

宿主对象
所有非本地对象都是宿主对象(host object),即由 ECMAScript 实现的宿主环境提供的对象。
所有 BOM 和 DOM 对象都是宿主对象。

作用域指的是变量的适用范围。
ECMAScript 中只存在一种作用域 - 公用作用域。ECMAScript 中的所有对象的所有属性和方法都是公用的。

静态作用域
静态作用域定义的属性和方法任何时候都能从同一位置访问。在 Java 中,类可具有属性和方法,无需实例化该类的对象,即可访问这些属性和方法,例如 java.net.URLEncoder 类,它的函数 encode() 就是静态方法。

ECMAScript 没有静态作用域
严格来说,ECMAScript 并没有静态作用域。不过,它可以给构造函数提供属性和方法。还记得吗,构造函数只是函数。函数是对象,对象可以有属性和方法。例如:
function sayHello() {
  alert("hello");
}

sayHello.alternate = function() {
  alert("hi");
}

sayHello(); //输出 "hello"
sayHello.alternate(); //输出 "hi"

-------------------------------------------------------
关键字 this 总是指向调用该方法的对象.
var oCar = new Object;
oCar.color = "red";
oCar.showColor = function() {
  alert(this.color); //this 等于 oCar
};

oCar.showColor(); //输出 "red"


使用 this 的原因
为什么使用 this 呢?因为在实例化对象时,总是不能确定开发者会使用什么样的变量名。使用 this,即可在任何多个地方重用同一个函数。

注意,引用对象的属性时,必须使用 this 关键字。


你可能感兴趣的:(Javascript高级编程)