Heim > Artikel > Web-Frontend > Vertieftes Verständnis von „Javascript Advanced Programming“
Javascript Advanced Programming Dieses Buch enthält viel Inhalt und ist sehr umfangreich. Ich hoffe, dass auch andere Leute, die keine Zeit haben, diese Auszugsreihe lesen und allgemein den Kerninhalt des Buches lernen können.
Der Inhalt mit grünem Hintergrund ist der Originalinhalt, den ich für bemerkenswerter halte.
Der Inhalt mit dem gelben Hintergrund ist der Originalinhalt, den ich für sehr wichtig halte.
Mein Verständnis wird in blauer Schrift markiert.
Dieses Kapitel hat viel Inhalt und ist relativ wichtig. Es wird in zwei Teilen aufgezeichnet.
Innerhalb einer Funktion gibt es zwei spezielle Objekte: Argumente und This. Darunter wurden Argumente in Kapitel 3 eingeführt. Es handelt sich um ein Array-ähnliches Objekt, das alle an die Funktion übergebenen Parameter enthält. Obwohl der Hauptzweck von Argumenten darin besteht, Funktionsparameter zu speichern, verfügt dieses Objekt auch über ein Attribut namens callee, das einen Zeiger auf die Funktion darstellt, die das Argumentobjekt besitzt. Bitte schauen Sie sich die folgende sehr klassische Fakultätsfunktion an:
function factorial(num){if (num <=1) {return 1; } else {return num * factorial(num-1) } }Die Definition der Fakultätsfunktion erfordert im Allgemeinen einen rekursiven Algorithmus, wie im obigen Code gezeigt Wenn ein Name vorhanden ist und sich der Name in Zukunft nicht ändern wird, ist diese Definition kein Problem. Das Problem besteht jedoch darin, dass die Ausführung dieser Funktion eng mit dem Funktionsnamen „Fakultät“ verknüpft ist. Um diese enge Kopplung zu beseitigen, kann arguments.callee wie folgt verwendet werden.
function factorial(num){if (num <=1) {return 1; } else {return num * arguments.callee(num-1) } }
verwendet wird. Zum Beispiel:
var trueFactorial = factorial; factorial = function(){return 0; }; alert(trueFactorial(5)); //120alert(factorial(5)); //0
在此,变量 trueFactorial 获得了 factorial 的值,实际上是在另一个位置上保存了一个函数的指针。然后,我们又将一个简单地返回 0 的函数赋值给 factorial 变量。如果像原来的 factorial()那样不使用 arguments.callee,调用 trueFactorial()就会返回 0。可是,在解除了函数体内的代码与函数名的耦合状态之后, trueFactorial()仍然能够正常地计算阶乘;至于 factorial(),它现在只是一个返回 0 的函数。
函数内部的另一个特殊对象是 this,其行为与 Java 和 C#中的 this 大致类似。换句话说, this引用的是函数据以执行的环境对象——或者也可以说是 this 值(当在网页的全局作用域中调用函数时,this 对象引用的就是 window)。来看下面的例子。
window.color = "red";var o = { color: "blue" };function sayColor(){ alert(this.color); } sayColor(); //"red"o.sayColor = sayColor; o.sayColor(); //"blue"
上面这个函数 sayColor()是在全局作用域中定义的,它引用了 this 对象。由于在调用函数之前,this 的值并不确定,因此 this 可能会在代码执行过程中引用不同的对象。当在全局作用域中调用sayColor()时, this 引用的是全局对象 window;换句话说,对 this.color 求值会转换成对window.color 求值,于是结果就返回了"red"。而当把这个函数赋给对象 o 并调用 o.sayColor()时,this 引用的是对象 o,因此对 this.color 求值会转换成对 o.color 求值,结果就返回了"blue"。
请读者一定要牢记,函数的名字仅仅是一个包含指针的变量而已。因此,即使是在不同的环境中执行,全局的 sayColor()函数与 o.sayColor()指向的仍然是同一个函数。
ECMAScript 5 也规范化了另一个函数对象的属性:caller。除了 Opera 的早期版本不支持,其他浏览器都支持这个 ECMAScript 3 并没有定义的属性。这个属性中保存着调用当前函数的函数的引用,如果是在全局作用域中调用当前函数,它的值为 null。例如:
function outer(){ inner(); }function inner(){ alert(inner.caller); } outer();
以上代码会导致警告框中显示 outer()函数的源代码。因为 outer()调用了 inter(),所以inner.caller 就指向 outer()。为了实现更松散的耦合,也可以通过 arguments.callee.caller来访问相同的信息。
function outer(){ inner(); }function inner(){ alert(arguments.callee.caller); } outer();
IE、 Firefox、 Chrome 和 Safari 的所有版本以及 Opera 9.6 都支持 caller 属性。
当函数在严格模式下运行时,访问 arguments.callee 会导致错误。 ECMAScript 5 还定义了arguments.caller 属性,但在严格模式下访问它也会导致错误,而在非严格模式下这个属性始终是undefined。定义这个属性是为了分清 arguments.caller 和函数的 caller 属性。以上变化都是为了加强这门语言的安全性,这样第三方代码就不能在相同的环境里窥视其他代码了。严格模式还有一个限制:不能为函数的 caller 属性赋值,否则会导致错误。
前面曾经提到过, ECMAScript 中的函数是对象,因此函数也有属性和方法。每个函数都包含两个属性: length 和 prototype。其中, length 属性表示函数希望接收的命名参数的个数,如下面的例子所示。
function sayName(name){ alert(name); }function sum(num1, num2){return num1 + num2; }function sayHi(){ alert("hi"); } alert(sayName.length); //1alert(sum.length); //2alert(sayHi.length); //0
在 ECMAScript 核心所定义的全部属性中,最耐人寻味的就要数 prototype 属性了。对于ECMAScript 中的引用类型而言, prototype 是保存它们所有实例方法的真正所在。换句话说,诸如toString()和 valueOf()等方法实际上都保存在 prototype 名下,只不过是通过各自对象的实例访问罢了。在创建自定义引用类型以及实现继承时, prototype 属性的作用是极为重要的(第 6 章将详细介绍)。在 ECMAScript 5 中, prototype 属性是不可枚举的,因此使用 for-in 无法发现。
每个函数都包含两个非继承而来的方法: apply()和 call()。这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内 this 对象的值。首先, apply()方法接收两个参数:一个是在其中运行函数的作用域,另一个是参数数组。其中,第二个参数可以是 Array 的实例,也可以是arguments 对象。例如:
function sum(num1, num2){return num1 + num2; }function callSum1(num1, num2){return sum.apply(this, arguments); // 传入 arguments 对象}function callSum2(num1, num2){return sum.apply(this, [num1, num2]); // 传入数组} alert(callSum1(10,10)); //20alert(callSum2(10,10)); //20
在上面这个例子中, callSum1()在执行 sum()函数时传入了 this 作为 this 值(因为是在全局作用域中调用的,所以传入的就是 window 对象)和 arguments 对象。而 callSum2 同样也调用了sum()函数,但它传入的则是 this 和一个参数数组。这两个函数都会正常执行并返回正确的结果。
call()方法与 apply()方法的作用相同,它们的区别仅在于接收参数的方式不同。对于 call()方法而言,第一个参数是 this 值没有变化,变化的是其余参数都直接传递给函数。换句话说,在使用call()方法时,传递给函数的参数必须逐个列举出来,如下面的例子所示。
function sum(num1, num2){return num1 + num2; }function callSum(num1, num2){return sum.call(this, num1, num2); } alert(callSum(10,10)); //20
在使用 call()方法的情况下, callSum()必须明确地传入每一个参数。结果与使用 apply()没有什么不同。至于是使用 apply()还是 call(),完全取决于你采取哪种给函数传递参数的方式最方便。如果你打算直接传入 arguments 对象,或者包含函数中先接收到的也是一个数组,那么使用 apply()肯定更方便;否则,选择 call()可能更合适。(在不给函数传递参数的情况下,使用哪个方法都无所谓。)
事实上,传递参数并非 apply()和 call()真正的用武之地;它们真正强大的地方是能够扩充函数赖以运行的作用域。下面来看一个例子。
window.color = "red";var o = { color: "blue" };function sayColor(){ alert(this.color); } sayColor(); //redsayColor.call(this); //redsayColor.call(window); //redsayColor.call(o); //blue
这个例子是在前面说明 this 对象的示例基础上修改而成的。这一次, sayColor()也是作为全局函数定义的,而且当在全局作用域中调用它时,它确实会显示"red"——因为对 this.color 的求值会转换成对 window.color 的求值。而 sayColor.call(this)和 sayColor.call(window),则是两种显式地在全局作用域中调用函数的方式,结果当然都会显示"red"。但是,当运行 sayColor.call(o)时,函数的执行环境就不一样了,因为此时函数体内的 this 对象指向了 o,于是结果显示的是"blue"。
使用 call()(或 apply())来扩充作用域的最大好处,就是对象不需要与方法有任何耦合关系。在前面例子的第一个版本中,我们是先将 sayColor()函数放到了对象 o 中,然后再通过 o 来调用它的;而在这里重写的例子中,就不需要先前那个多余的步骤了。
ECMAScript 5 还定义了一个方法: bind()。这个方法会创建一个函数的实例,其 this 值会被绑定到传给 bind()函数的值。例如:
window.color = "red";var o = { color: "blue" };function sayColor(){ alert(this.color); }var objectSayColor = sayColor.bind(o); objectSayColor(); //blue
Hier ruft sayColor() bind() auf und übergibt das Objekt o, wodurch die Funktion objectSayColor() erstellt wird. Die Funktion this value of object
SayColor() ist gleich o, sodass Sie „blau“ sehen, selbst wenn diese Funktion im globalen Bereich aufgerufen wird. Die Vorteile dieser Technik finden Sie in Kapitel 22.
Browser, die die bind()-Methode unterstützen, sind IE9+, Firefox 4+, Safari 5.1+, Opera 12+ und Chrome.
Die von jeder Funktion geerbten Methoden toLocaleString() und toString() geben immer den Code der Funktion zurück. Das Format des Rückgabecodes variiert zwischen Browsern – einige geben denselben Code wie den Funktionscode im Quellcode zurück, während andere eine interne Darstellung des Funktionscodes zurückgeben, dh der Parser entfernt Kommentare und ändert den geänderten Code . Aufgrund dieser Unterschiede können wir auf der Grundlage der von diesen beiden Methoden zurückgegebenen Ergebnisse nichts Wesentliches tun. Diese Informationen können jedoch beim Debuggen des Codes nützlich sein. Eine andere geerbte valueOf()-Methode gibt ebenfalls nur den Funktionscode zurück.
Um die Manipulation grundlegender Typwerte zu erleichtern, stellt ECMAScript außerdem drei spezielle Referenztypen bereit: Boolean, Number und String. Diese Typen ähneln den anderen in diesem Kapitel vorgestellten Referenztypen, weisen jedoch auch ein spezielles Verhalten auf, das ihren jeweiligen Basistypen entspricht. Tatsächlich wird jedes Mal, wenn ein Basistypwert gelesen wird, im Hintergrund ein entsprechendes Basis-Wrapper-Typobjekt erstellt, das es uns ermöglicht, einige Methoden aufzurufen, um diese Daten zu bearbeiten. Betrachten Sie das folgende Beispiel.
var s1 = "some text";
var s2 = s1.substring(2);
Die Variable s1 in diesem Beispiel enthält eine Zeichenfolge, bei der es sich natürlich um einen Basistypwert handelt. Die nächste Zeile ruft die Methode substring() von s1 auf und speichert das zurückgegebene Ergebnis in s2. Wir wissen, dass primitive Werte keine Objekte sind, daher sollten sie logischerweise keine Methoden haben (obwohl sie, wie wir es wünschen, solche haben). Damit wir diese intuitive Bedienung erreichen können, wurden tatsächlich eine Reihe von Prozessen automatisch im Hintergrund ausgeführt. Wenn die zweite Codezeile auf s1 zugreift, befindet sich der Zugriffsprozess im Lesemodus, dh der Wert dieser Zeichenfolge soll aus dem Speicher gelesen werden. Beim Zugriff auf eine Zeichenfolge im Lesemodus wird die folgende Verarbeitung automatisch im Hintergrund abgeschlossen.
(1) Erstellen Sie eine Instanz vom Typ String
(2) Rufen Sie die angegebene Methode für die Instanz auf; >
(3) Zerstöre diese Instanz.Die oben genannten drei Schritte können Sie sich als Ausführung des folgenden ECMAScript-Codes vorstellen.
var s1 = new String("some text");
var s2 = s1.substring(2);
s1 = null;
Nach dieser Verarbeitung entspricht der grundlegende Zeichenfolgenwert dem des Objekts. Darüber hinaus gelten die oben genannten drei Schritte auch für boolesche und numerische Werte, die den Typen Boolean bzw. Number entsprechen. Der Hauptunterschied zwischen Referenztypen und grundlegenden Wrapper-Typen ist die Lebensdauer des Objekts. Instanzen von Referenztypen, die mit dem neuen Operator erstellt wurden, bleiben im Speicher, bis der Ausführungsfluss den aktuellen Bereich verlässt. Das automatisch erstellte Basispakettypobjekt existiert nur in dem Moment, in dem eine Codezeile ausgeführt wird, und wird dann sofort zerstört. Dies bedeutet, dass wir zur Laufzeit keine Eigenschaften und Methoden zu primitiven Typwerten hinzufügen können.
Sehen Sie sich das folgende Beispiel an:
var s1 = "some text";
s1.color = "red";
alert(s1.color); //undefined 在此,第二行代码试图为字符串 s1 添加一个 color 属性。但是,当第三行代码再次访问 s1 时,其 color 属性不见了。问题的原因就是第二行创建的 String 对象在执行第三行代码时已经被销毁了。第三行代码又创建自己的 String 对象,而该对象没有 color 属性。当然,可以显式地调用 Boolean、 Number 和 String 来创建基本包装类型的对象。不过,应该在绝对必要的情况下再这样做,因为这种做法很容易让人分不清自己是在处理基本类型还是引用类型的值。对基本包装类型的实例调用 typeof 会返回"object",而且所有基本包装类型的对象都会被转换为布尔值 true。 Object 构造函数也会像工厂方法一样,根据传入值的类型返回相应基本包装类型的实例。例如: var obj = new Object("some text"); alert(obj instanceof String); //true 把字符串传给 Object 构造函数,就会创建 String 的实例;而传入数值参数会得到 Number 的实例,传入布尔值参数就会得到 Boolean 的实例。 要注意的是,使用 new 调用基本包装类型的构造函数,与直接调用同名的转型函数是不一样的。例如: 在这个例子中,变量 number 中保存的是基本类型的值 25,而变量 obj 中保存的是 Number 的实例。要了解有关转型函数的更多信息,请参考第 3 章。 尽管我们不建议显式地创建基本包装类型的对象,但它们操作基本类型值的能力还是相当重要的。而每个基本包装类型都提供了操作相应值的便捷方法。 5.6.1 Boolean类型 Boolean 类型是与布尔值对应的引用类型。要创建 Boolean 对象,可以像下面这样调用 Boolean构造函数并传入 true 或 false 值。 var booleanObject = new Boolean(true); Boolean 类型的实例重写了 valueOf()方法,返回基本类型值 true 或 false;重写了 toString() 方法,返回字符串"true"和"false"。可是, Boolean 对象在 ECMAScript 中的用处不大,因为它经常会造成人们的误解。其中最常见的问题就是在布尔表达式中使用 Boolean 对象,例如: 前面讨论过,布尔表达式中的所有对象都会被转换为 true,因此 falseObject 对象在布尔表达式中代表的是 true。结果, true && true 当然就等于 true 了。 基本类型与引用类型的布尔值还有两个区别。首先, typeof 操作符对基本类型返回"boolean",而对引用类型返回"object"。其次,由于 Boolean 对象是 Boolean 类型的实例,所以使用 instanceof操作符测试 Boolean 对象会返回 true,而测试基本类型的布尔值则返回 false。例如: 理解基本类型的布尔值与 Boolean 对象之间的区别非常重要——当然,我们的建议是永远不要使用 Boolean 对象。 5.6.2 Number类型 Number 是与数字值对应的引用类型。要创建 Number 对象,可以在调用 Number 构造函数时向其中传递相应的数值。下面是一个例子。 var numberObject = new Number(10); 与 Boolean 类型一样, Number 类型也重写了 valueOf()、 toLocaleString()和 toString() 方法。重写后的 valueOf()方法返回对象表示的基本类型的数值,另外两个方法则返回字符串形式的数值。我们在第 3 章还介绍过,可以为 toString()方法传递一个表示基数的参数,告诉它返回几进制数值的字符串形式,如下面的例子所示。 除了继承的方法之外, Number 类型还提供了一些用于将数值格式化为字符串的方法。 其中, toFixed()方法会按照指定的小数位返回数值的字符串表示,例如: var num = 10; alert(num.toFixed(2)); //"10.00" NumberTypeExample01.htm 这里给 toFixed()方法传入了数值 2,意思是显示几位小数。于是,这个方法返回了"10.00",即以 0 填补了必要的小数位。如果数值本身包含的小数位比指定的还多,那么接近指定的最大小数位的值就会舍入,如下面的例子所示。 var num = 10.005; alert(num.toFixed(2)); //"10.01" 能够自动舍入的特性,使得 toFixed()方法很适合处理货币值。但需要注意的是,不同浏览器给这个方法设定的舍入规则可能会有所不同。在给 toFixed()传入 0 的情况下, IE8 及之前版本不能正确舍入范围在{(-0.94,-0.5],[0.5,0.94)}之间的值。对于这个范围内的值, IE 会返回0,而不是1或1;其他浏览器都能返回正确的值。 IE9 修复了这个问题。 5.6.3 String类型 String 类型是字符串的对象包装类型,可以像下面这样使用 String 构造函数来创建。 var stringObject = new String("hello world"); String 对象的方法也可以在所有基本的字符串值中访问到。其中,继承的 valueOf()、toLocale String()和 toString()方法,都返回对象所表示的基本字符串值。 String 类型的每个实例都有一个 length 属性,表示字符串中包含多个字符。来看下面的例子。 var stringValue = "hello world"; alert(stringValue.length); //"11" 这个例子输出了字符串"hello world"中的字符数量,即"11"。应该注意的是,即使字符串中包含双字节字符(不是占一个字节的 ASCII 字符),每个字符也仍然算一个字符。 String 类型提供了很多方法,用于辅助完成对 ECMAScript 中字符串的解析和操作。 1. 字符方法 两个用于访问字符串中特定字符的方法是: charAt()和 charCodeAt() 2. 字符串操作方法 下面介绍与操作字符串有关的几个方法。第一个就是 concat(),用于将一或多个字符串拼接起来,返回拼接得到的新字符串。先来看一个例子。 ECMAScript还提供了三个基于子字符串创建新字符串的方法:slice()、substr()和substring()。这三个方法都会返回被操作字符串的一个子字符串,而且也都接受一或两个参数。第一个参数指定子字符串的开始位置,第二个参数(在指定的情况下)表示子字符串到哪里结束。具体来说, slice()和substring()的第二个参数指定的是子字符串最后一个字符后面的位置。而 substr()的第二个参数指定的则是返回的字符个数。如果没有给这些方法传递第二个参数,则将字符串的长度作为结束位置。与concat()方法一样, slice()、 substr()和 substring()也不会修改字符串本身的值——它们只是返回一个基本类型的字符串值,对原始字符串没有任何影响。请看下面的例子。 3. 字符串位置方法 有两个可以从字符串中查找子字符串的方法: indexOf()和 lastIndexOf()。这两个方法都是从 一个字符串中搜索给定的子字符串,然后返子字符串的位置(如果没有找到该子字符串,则返回-1)。这两个方法的区别在于: indexOf()方法从字符串的开头向后搜索子字符串,而 lastIndexOf()方法是从字符串的末尾向前搜索子字符串。还是来看一个例子吧。 var stringValue = "hello world"; alert(stringValue.indexOf("o")); //4 alert(stringValue.lastIndexOf("o")); //7 4. trim()方法 ECMAScript 5 为所有字符串定义了 trim()方法。这个方法会创建一个字符串的副本,删除前置及后缀的所有空格,然后返回结果。例如: 5. 字符串大小写转换方法 接下来我们要介绍的是一组与大小写转换有关的方法。 ECMAScript 中涉及字符串大小写转换的方法有 4 个: toLowerCase()、 toLocaleLowerCase()、 toUpperCase()和 toLocaleUpperCase() 7. localeCompare()方法 与操作字符串有关的最后一个方法是 localeCompare(),这个方法比较两个字符串,并返回下列值中的一个: q 如果字符串在字母表中应该排在字符串参数之前,则返回一个负数(大多数情况下是-1,具体的值要视实现而定); q 如果字符串等于字符串参数,则返回 0; q 如果字符串在字母表中应该排在字符串参数之后,则返回一个正数(大多数情况下是 1,具体的值同样要视实现而定)。 下面是几个例子。 ECMA-262 definiert integrierte Objekte als: „Von der ECMAScript-Implementierung bereitgestellte Objekte, die nicht von der Hostumgebung abhängen. Diese Objekte sind vorhanden, bevor das ECMAScript-Programm ausgeführt wird. Dies bedeutet, dass Entwickler integrierte Objekte nicht explizit instanziieren müssen, da sie bereits instanziiert sind. Die meisten integrierten Objekte wie Object, Array und String haben wir bereits vorgestellt. ECMA-262 definiert außerdem zwei einzelne integrierte Objekte: Global und Math. 5.7.1 Globales Objekt Das globale Objekt kann als das speziellste Objekt in ECMAScript bezeichnet werden. Denn egal aus welchem Blickwinkel man es betrachtet, dieses Objekt existiert nicht. Das globale Objekt in ECMAScript ist gewissermaßen als das ultimative „Catch-All-Objekt“ definiert. Mit anderen Worten: Eigenschaften und Methoden, die zu keinem anderen Objekt gehören, sind letztendlich dessen Eigenschaften und Methoden. Tatsächlich gibt es keine globalen Variablen oder Funktionen; alle im globalen Bereich definierten Eigenschaften und Funktionen sind Eigenschaften des globalen Objekts. Die zuvor in diesem Buch vorgestellten Funktionen wie isNaN(), isFinite(), parseInt() und parseFloat() sind eigentlich alle Methoden des Global-Objekts. Darüber hinaus enthält das Global-Objekt noch einige andere Methoden. 1. URI-Kodierungsmethode Die Methoden encodeURI() und encodeURIComponent() des globalen Objekts können URI (Uniform Resource) kodieren > Identifiers, Universal Resource Identifiers) werden codiert, um an den Browser gesendet zu werden. Bestimmte Zeichen, z. B. Leerzeichen, können nicht in einen gültigen URI enthalten sein. Diese beiden URI-Kodierungsmethoden können den URI kodieren. Sie ersetzen alle ungültigen Zeichen durch eine spezielle UTF-8-Kodierung, damit der Browser sie akzeptieren und verstehen kann. 2. eval()-Methode Jetzt stellen wir die letzte vor – wahrscheinlich die leistungsstärkste Methode in der gesamten ECMAScript-Sprache: eval (). Die eval()-Methode ist wie ein vollständiger ECMAScript-Parser, sie akzeptiert nur einen Parameter, den ECMAScript- (oder JavaScript-)String, der ausgeführt werden soll. Schauen Sie sich das folgende Beispiel an: eval("alert('hi')"); Die Wirkung dieser Codezeile ist entspricht der folgenden Codezeile: alert("hi"); Wenn der Parser die eval()-Methode feststellt im Code aufgerufen wird, analysiert es die übergebenen Argumente als tatsächliche ECMAScript-Anweisungen und fügt die Ausführungsergebnisse an ihren ursprünglichen Positionen ein. Über eval() ausgeführter Code wird als Teil der Ausführungsumgebung betrachtet, die den Aufruf enthält, sodass der ausgeführte Code dieselbe Gültigkeitsbereichskette wie diese Ausführungsumgebung hat. Das bedeutet, dass über eval() ausgeführter Code auf Variablen verweisen kann, die in der enthaltenden Umgebung definiert sind, zum Beispiel: var msg = "hello world"; eval("alert(msg)"); //"hello world" Es ist ersichtlich, dass die Variable msg außerhalb der Umgebung definiert ist, in der eval() aufgerufen wird , aber der dort aufgerufene Alert() kann immer noch „Hallo Welt“ anzeigen. Dies liegt daran, dass die zweite Codezeile oben schließlich durch eine echte Codezeile ersetzt wird. Ebenso können wir auch eine Funktion im eval()-Aufruf definieren und dann im externen Code des Aufrufs auf die Funktion verweisen: eval("function sayHi() { warning (' hi'); }"); sayHi(); Offensichtlich ist die Funktion sayHi() innerhalb von eval() definiert. Da aber der Aufruf von eval() irgendwann durch den eigentlichen Code ersetzt wird, der die Funktion definiert, kann sayHi() in der nächsten Zeile aufgerufen werden. Das Gleiche gilt für Variablen: eval("var msg = 'hello world'; "); alert(msg); //"hello world" 在 eval()中创建的任何变量或函数都不会被提升,因为在解析代码的时候,它们被包含在一个字符串中;它们只在 eval()执行的时候创建。 严格模式下,在外部访问不到 eval()中创建的任何变量或函数,因此前面两个例子都会导致错误。同样,在严格模式下,为 eval 赋值也会导致错误: "use strict"; eval = "hi"; //causes error 能够解释代码字符串的能力非常强大,但也非常危险。因此在使用 eval()时必须极为谨慎,特别是在用它执行用户输入数据的情况下。否则,可能会有恶意用户输入威胁你的站点或应用程序安全的代码(即所谓的代码注入)。 3. Global 对象的属性 Global 对象还包含一些属性,其中一部分属性已经在本书前面介绍过了。例如,特殊的值 undefined、 NaN 以及 Infinity 都是 Global 对象的属性。此外,所有原生引用类型的构造函数,像Object 和 Function,也都是 Global 对象的属性。下表列出了 Global 对象的所有属性。 undefined 特殊值undefined Date 构造函数Date NaN 特殊值NaN RegExp 构造函数RegExp Infinity 特殊值Infinity Error 构造函数Error Object 构造函数Object EvalError 构造函数EvalError Array 构造函数Array RangeError 构造函数RangeError Function 构造函数Function ReferenceError 构造函数ReferenceError Boolean 构造函数Boolean SyntaxError 构造函数SyntaxError String 构造函数String TypeError 构造函数TypeError Number 构造函数Number URIError 构造函数URIError ECMAScript 5 明确禁止给 undefined、 NaN 和 Infinity 赋值,这样做即使在非严格模式下也会导致错误。 4. window 对象 ECMAScript 虽然没有指出如何直接访问 Global 对象,但 Web 浏览器都是将这个全局对象作为window 对象的一部分加以实现的。因此,在全局作用域中声明的所有变量和函数,就都成为了 window对象的属性。来看下面的例子。 Neben der Rolle des von ECMAScript spezifizierten globalen Objekts übernimmt das Fensterobjekt in JavaScript auch viele andere Aufgaben. Das Fensterobjekt wird in Kapitel 8 ausführlich besprochen, wenn wir das Browserobjektmodell besprechen. 5.7.2 Math-Objekt ECMAScript bietet auch einen gemeinsamen Speicherort zum Speichern mathematischer Formeln und Informationen, das Math-Objekt. Die vom Math-Objekt bereitgestellten Berechnungsfunktionen sind viel schneller als die Berechnungsfunktionen, die wir direkt in JavaScript schreiben. Das Math-Objekt stellt außerdem Eigenschaften und Methoden bereit, die bei der Durchführung dieser Berechnungen helfen. 1. Eigenschaften des Math-Objekts Die meisten im Math-Objekt enthaltenen Eigenschaften sind spezielle Werte, die in verwendet werden können mathematische Berechnungen. In der folgenden Tabelle sind diese Eigenschaften aufgeführt.
Während die Erörterung der Bedeutung und Verwendung dieser Werte den Rahmen dieses Buches sprengt, können Sie sie tatsächlich verwenden sie jederzeit. 2. Methoden min() und max() Das Math-Objekt enthält auch viele Methoden, die bei der Vervollständigung einfacher und komplexer mathematischer Berechnungen helfen . Unter diesen werden die Methoden min() und max() verwendet, um die Mindest- und Höchstwerte in einer Reihe von Werten zu bestimmen. Beide Methoden können eine beliebige Anzahl numerischer Argumente akzeptieren, wie im folgenden Beispiel gezeigt. var max = Math.max(3, 54, 32, 16); alert(max); //54 var min = Math.min(3, 54, 32, 16); alert(min); //3 3. Rundungsmethoden Hier sind einige Methoden zum Runden von Dezimalwerten in ganze Zahlen: Math.ceil(), Math.floor( ) und Math .runden(). Diese drei Methoden folgen jeweils den folgenden Rundungsregeln: Math.ceil() führt eine Aufwärtsrundung durch, das heißt, es rundet immer Werte werden auf die nächste ganze Zahl aufgerundet; Math.floor() führt eine Abrundung durch, d. h. es rundet den Wert immer auf die nächste ganze Zahl ab; Math.round() führt eine Standardrundung durch, d. h. es rundet einen Wert immer auf die nächste ganze Zahl (dies ist auch die Rundungsregel, die wir im Mathematikunterricht gelernt haben). 4. random()-Methode Math.random()-Methode gibt eine Zufallszahl zurück, die größer oder gleich 0 und kleiner als 1 ist . Für einige Websites ist diese Methode sehr praktisch, da damit einige berühmte Zitate und Nachrichtenereignisse nach dem Zufallsprinzip angezeigt werden können. Wenn Sie die folgende Formel anwenden, können Sie Math.random() verwenden, um einen Wert aus einem bestimmten Bereich von ganzen Zahlen zufällig auszuwählen. Wert = Math.floor(Math.random() * Gesamtzahl möglicher Werte + erster möglicher Wert) 5. Andere Methoden
Objekte werden im JavaScript-Referenztyp aufgerufen Werte, und es gibt einige integrierte Referenztypen, die zum Erstellen bestimmter Objekte verwendet werden können: Referenztypen ähneln Klassen in der traditionellen objektorientierten Struktur Aber die Umsetzung ist anders Object ist ein Basistyp, und alle anderen Typen erben grundlegende Verhaltensweisen von Object Der Array-Typ ist eine geordnete Liste einer Reihe von Werten und bietet außerdem Folgendes: Bietet Funktionen zum Bearbeiten und Konvertieren dieser Werte. Der Datumstyp bietet Informationen zu Datum und Uhrzeit, einschließlich des aktuellen Datums und der aktuellen Uhrzeit sowie zugehöriger Berechnungsfunktionen >RegExp-Typ ist eine Schnittstelle von ECMAScript, die reguläre Ausdrücke unterstützt und die grundlegendsten und einige erweiterte Funktionen für reguläre Ausdrücke bereitstellt. Funktionen sind eigentlich Instanzen des Funktionstyps, daher sind Funktionen auch Objekte und dies ist das markanteste Merkmal von JavaScript. Da es sich bei Funktionen um Objekte handelt, verfügen sie auch über Methoden, mit denen sich ihr Verhalten verbessern lässt. Aufgrund des grundlegenden Wrapper-Typs kann auf grundlegende Typwerte in JavaScript als Objekte zugegriffen werden. Die drei grundlegenden Wrapper-Typen sind: Boolean, Number und String. Im Folgenden sind ihre gemeinsamen Merkmale aufgeführt: Jeder Wrapper-Typ wird einem Basistyp mit demselben Namen zugeordnet Auf den Basistyp wird zugegriffen Beim Lesen des Typwerts wird ein Objekt des entsprechenden Basistyps erstellt, wodurch Datenoperationen erleichtert werden. Sobald die Anweisung zum Betrieb des Basistypwerts ausgeführt wird, wird das neu erstellte Objekt erstellt Der Verpackungsgegenstand wird umgehend vernichtet. Bevor der gesamte Code ausgeführt wird, sind bereits zwei integrierte Objekte im Bereich vorhanden: Global und Math. Auf das Global-Objekt kann in den meisten ECMAScript-Implementierungen nicht direkt zugegriffen werden. Webbrowser implementieren jedoch ein Fensterobjekt, das diese Rolle übernimmt. Globale Variablen und Funktionen sind Eigenschaften des globalen Objekts. Das Math-Objekt stellt viele Eigenschaften und Methoden bereit, die Sie bei der Durchführung komplexer mathematischer Berechnungsaufgaben unterstützen. var value = "25";var number = Number(value); //转型函数alert(typeof number); //"number"var obj = new Number(value); //构造函数alert(typeof obj); //"object"
var falseObject = new Boolean(false);var result = falseObject && true;
alert(result); //truevar falseValue = false;
result = falseValue && true;
alert(result); //false
alert(typeof falseObject); //objectalert(typeof falseValue); //booleanalert(falseObject instanceof Boolean); //truealert(falseValue instanceof Boolean); //false
var num = 10;
alert(num.toString()); //"10"alert(num.toString(2)); //"1010"alert(num.toString(8)); //"12"alert(num.toString(10)); //"10"alert(num.toString(16)); //"a"NumberTypeExample01.htm
var stringValue = "hello ";var result = stringValue.concat("world");
alert(result); //"hello world"alert(stringValue); //"hello"
var stringValue = "hello world";
alert(stringValue.slice(3)); //"lo world"alert(stringValue.substring(3)); //"lo world"alert(stringValue.substr(3)); //"lo world"alert(stringValue.slice(3, 7)); //"lo w"alert(stringValue.substring(3,7)); //"lo w"alert(stringValue.substr(3, 7)); //"lo worl"
var stringValue = " hello world ";var trimmedStringValue = stringValue.trim();
alert(stringValue); //" hello world "alert(trimmedStringValue); //"hello world"
var stringValue = "yellow";
alert(stringValue.localeCompare("brick")); //1alert(stringValue.localeCompare("yellow")); //0alert(stringValue.localeCompare("zoo")); //-1
5.7 Einzelne integrierte Objekte
var color = "red";function sayColor(){
alert(window.color);
}
window.sayColor(); //"red"
5.8 Zusammenfassung
Das obige ist der detaillierte Inhalt vonVertieftes Verständnis von „Javascript Advanced Programming“. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!