天天看點

label标簽和argument方法重載以及eval函數(詳解)

一 <label>标簽及for屬性

Label對象

表示一個HTML<keygen>元素

通路Label對象

使用getElementById()來通路<label>元素

var x=document.getElementById("myLabel");

建立Label對象

var x=document.createElement("LABEL");

Label對象屬性

control  描述:傳回标注的控件

form     描述:傳回一個包含Label的表單的引用

htmlFor  描述:設定或傳回label的for屬性的值

label的for屬性總結

1.定義:for屬性規定label與哪個表單元素綁定。

<label>是專門為<input>元素服務的,為其定義标記;

label和表單控件綁定方式有兩種:

方法一:将表單控件作為label的内容,這種就是隐士綁定

此時,不需要for屬性,綁定的控件也不需要id屬性

隐士綁定:

<label>Date of Birth:<input type="text" name="DofB" /></label>

方法二:為label标簽下的for屬性命名一個目标表單的id,這種就是顯示綁定。

顯式綁定:

<label for="SSN">Social Security Number:</label>

<input type="text" name="SocSecNum" id="SSN" />

二、為什麼要給label上面加上for屬性

給 label 加了 for 屬性綁定了input控件後,可以提高滑鼠使用者的使用者體檢。

如果在label 元素内點選文本,就會觸發此控件,也就是說,當使用者渲染該标簽時,浏覽器就會自動将焦點轉到和标簽相關的表單控件上。

Label htmlFor 屬性

傳回 label 的 for 屬性的值:

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8">

<title></title>

</head>

<body>

<form>

<label id="myLabel" for="male">Male</label>

<input type="radio" name="sex" id="male" value="male"><br>

</form>

<p>點選“嘗試一下”按鈕傳回 label 的 for 屬性的值。</p>

<p id="demo"></p>

<button οnclick="myFunction()">嘗試一下</button>

<script>

function myFunction(){

    var x = document.getElementById("myLabel").htmlFor;

    document.getElementById("demo").innerHTML=x;

}

</script>

</body>

</html>

定義和用法

htmlFor 屬性設定或傳回 lable 的 for 屬性的值。

for 屬性指定 label 要綁定到哪一個表單元素。

文法

傳回 htmlFor 屬性:

labelObject.htmlFor

設定 htmlFor 屬性:

labelObject.htmlFor=id

屬性值

id     label 要綁定的元素的 id。

技術細節

傳回值: 字元串,表示 label 要綁定的元素的 id。

二 argument方法重載

1. parameter是指函數定義中參數,而argument指的是函數調用時的實際參數。

2. 簡略描述為:parameter=形參(formal parameter), argument=實參(actual parameter)。

3. 在不很嚴格的情況下,現在二者可以混用,一般用argument,而parameter則比較少用。

<form>

        <h2>方法重載</h2>

        <input type="button" value="計算平方" οnclick="myMethod(12)" />

        <input type="button" value="計算加法" οnclick="myMethod(12,45)" />

        </form>

    </body>

    <script type="text/javascript">

        function myMethod(){

            if(arguments.length==1){

                //計算平方

                var n=parseInt(arguments[0]);

                alert(n+" 的平方為:"+n*n);

            }else if(arguments.length==2){

                //計算和

                var n=parseInt(arguments[0]);

                var m=parseInt(arguments[1]);

                var result=n+m;

                alert(n+"與"+m+"的和為:"+result);

            }

        }

    </script>

三 eval函數

文法

eval(string)

參數

string

    一個表示 JavaScript 表達式、語句或一系列語句的字元串。表達式可以包含變量與已存在對象的屬性。

傳回值

傳回字元串中代碼的傳回值。如果傳回值為空,則傳回 undefined。

描述

eval() 是全局對象的一個函數屬性。

eval() 的參數是一個字元串。如果字元串表示的是表達式,eval() 會對表達式進行求值。如果參數表示一個或多個 JavaScript 語句,那麼eval() 就會執行這些語句。注意不要用 eval() 來執行一個算術表達式:因為 JavaScript可以自動為算術表達式求值。如果你以字元串的形式構造算術表達式,則可以用 eval() 在随後對其求值。

例如,假設你有一個變量 x,您可以通過将表達式的字元串值(例如 3 * x +2)指派給一個變量,然後在你的代碼後面的其他地方調用 eval(),來推遲涉及 x 的表達式的求值。

如果 eval() 的參數不是字元串, eval() 會将參數原封不動地傳回。在下面的例子中,String 構造器被指定,而 eval() 傳回String 對象而不是執行字元串。

eval(new String("2 + 2")); // 傳回了包含"2 + 2"的字元串對象

eval("2 + 2");             // returns 4

你可以使用一些通用的方法來繞過這個限制,例如使用 toString()。

var expression = new String("2 + 2");

eval(expression.toString());

如果你間接的使用 eval(),比如通過一個引用來調用它,而不是直接的調用eval。 從 ECMAScript 5 起,它工作在全局作用域下,而不是局部作用域中。

這就意味着,例如,下面的代碼的作用聲明建立一個全局函數,并且 eval 中的這些代碼在執行期間不能在被調用的作用域中通路局部變量。

function test() {

  var x = 2, y = 4;

  console.log(eval('x + y'));  // 直接調用,使用本地作用域,結果是 6

  var geval = eval; // 等價于在全局作用域調用

  console.log(geval('x + y')); // 間接調用,使用全局作用域,throws

ReferenceError 因為`x`未定義

  (0, eval)('x + y'); // 另一個間接調用的例子

​}

避免在不必要的情況下使用 eval!

eval() 是一個危險的函數, 它使用與調用者相同的權限執行代碼。如果你用eval() 運作的字元串代碼被惡意方(不懷好意的人)修改,您最終可能會在您的網頁/擴充程式的權限下,在使用者計算機上運作惡意代碼。更重要的是,第三方代碼可以看到某一個 eval() 被調用時的作用域,這也有可能導緻一些不同方式的攻擊。相似的 Function 就不容易被攻擊。

eval() 通常比其他替代方法更慢,因為它必須調用 JS 解釋器,而許多其他結構則可被現代 JS 引擎進行優化。

Bad code with eval:

function looseJsonParse(obj){

    return eval(obj);

}

console.log(looseJsonParse(

   "{a:(4-1), b:function(){}, c:new Date()}"

))

Better code without eval:

function looseJsonParse(obj){

    return Function('"use strict";return (' + obj + ')')();

}

console.log(looseJsonParse(

   "{a:(4-1), b:function(){}, c:new Date()}"

))

function Date(n){

    return

["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunda

y"][n%7 || 0];

}

function looseJsonParse(obj){

    return eval(obj);

}

console.log(looseJsonParse(

   "{a:(4-1), b:function(){}, c:new Date()}"

))

function Date(n){

    return

["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunda

y"][n%7 || 0];

}

function runCodeWithDateFunction(obj){

    return Function('"use strict";return (' + obj + ')')()(

        Date

    );

}

console.log(runCodeWithDateFunction(

   "function(Date){ return Date(5) }"

))

console.log(Function('"use strict";return(function(a){return a

(5)})')()(function(a){

return"Monday Tuesday Wednesday Thursday Friday Saturday

Sunday".split(" ")[a%7||0]}));

There are also additional safer (and faster!) alternatives to eval()

or Function() for common use-cases.

通路成員屬性

你不應該去使用 eval() 來将屬性名字轉化為屬性。考慮下面的這個例子,被通路對象的屬性在它被執行之前都會未知的。這裡可以用 eval 處理:

var obj = { a: 20, b: 30 };

var propName = getPropName(); // 傳回 "a" 或 "b"

eval( 'var result = obj.' + propsName )

但是,這裡并不是必須得使用 eval() 。事實上,這裡并不建議這樣使用。可以使用 屬性通路器 進行代替,它更快、更安全:

var obj = { a: 20, b: 30 }

var propName = getPropName(); // 傳回 "a" 或 "b"

var result = obj[ propName ]; // obj[ "a" ] 與 obj.a 等價

你還可以使用這個方法去通路子代的屬性。如下:

var obj = {a: {b: {c: 0}}};

var propPath = getPropPath(); // 例如傳回 "a.b.c"

eval( 'var result = obj.' + propPath )

這裡,可以通過分割屬性路徑、循環周遊不同的屬性,來避免 eval():

function getDescendantProp(obj, desc) {

  var arr = desc.split('.');

  while (arr.length) {

    obj = obj[arr.shift()];

  }

  return obj;

}

var obj = {a: {b: {c: 0}}};

var propPath = getPropPath(); // 例如傳回 "a.b.c"

var result = getDescendantProp(obj, propPath);

同樣的方法也可實作設定子代的屬性值:

function setDescendantProp(obj, desc, value) {

  var arr = desc.split('.');

  while (arr.length > 1) {

    obj = obj[arr.shift()];

  }

  return obj[arr[0]] = value;

}

var obj = {a: {b: {c: 0}}};

var propPath = getPropPath();  // 例如,傳回 "a.b.c"

var result = setDescendantProp(obj, propPath, 1);  // a.b.c 值為 1

使用函數而非代碼段

JavaScript 擁有 first-class functions,這意味着你可以将函數直接作為參數傳遞給其他接口,将他們儲存在變量中或者對象的屬性中,等等。很多DOM的API都用這種思路進行設計,你也可以(或者應該)這樣子設計你的代碼:

// 代替 setTimeout(" ... ", 1000) 寫法:

setTimeout(function() { ... }, 1000);

// 代替 elt.setAttribute("onclick", "...") 寫法:

elt.addEventListener('click', function() { ... } , false);

閉包 也有助于建立參數化函數而不用連接配接字元串。

解析 JSON(将字元串轉化為 JavaScript 對象)

如果你在調用 eval() 傳入的字元串參數中包含資料(如:一個數組“[1,2,3]”)而不是代碼,你應該考慮将其轉換為 JSON 對象,這允許你用JavaScript文法的子集來表示資料。在擴充中下載下傳JSON和JavaScript提示:因為 JSON 文法子集相對于 JavaScript 文法子集比較有局限性,很多在 JavaScript 中可用的特性在 JSON 中就不起作用了。比如,字尾逗号在JSON 中不支援,并且對象中的屬性名在 JSON 中必須用引号括起來。請務必使用 JSON 序列化方法來生成稍後将被解析為 JSON 的字元串。

盡量傳遞資料而非代碼

例如,設計為抓取網頁内容的擴充,可能會在XPath中定義抓取規則,而不是在JavaScript 代碼中。

以有限權限運作代碼

如果你必須執行這段代碼, 應考慮以更低的權限運作。此建議主要适用于擴充和 XUL 應用程式,可以使Components.utils.evalInSandbox 做到降低權限

使用 eval

在下面的代碼中,兩種包含了 eval() 的聲明都傳回了 42。第一種是對字元串"x + y + 1" 求值;第二種是對字元串 "42" 求值。

var x = 2;

var y = 39;

var z = "42";

eval("x + y + 1"); // returns 42

eval(z);           // returns 42

使用 eval 執行一串 JavaScript 語句下面的例子使用 eval() 來執行 str 字元串。這個字元串包含了如果 x 等于5,就打開一個Alert 對話框并對 z 指派 42,否則就對 z 指派 0 的JavaScript 語句。 當第二個聲明被執行,eval() 将會令字元串被執行,并最終傳回指派給 z 的 42。

var x = 5;

var str = "if (x == 5) {console.log('z is 42'); z = 42;} else z =

0;";

console.log('z is ', eval(str));

如果您定義了多個值,則會傳回最後一個值。

var x = 5;

var str = "if (x == 5) {console.log('z is 42'); z = 42; x = 420; }

else z = 0;";

console.log('x is ', eval(str)); // z is 42  x is 420

傳回值

eval 傳回最後一個表達式的值。

var str = 'if ( a ) { 1 + 1; } else { 1 + 2; }';

var a = true;

var b = eval(str);  // returns 2

console.log('b is : ' + b);

a = false;

b = eval(str);  // returns 3

console.log('b is : ' + b);

eval 中函數作為字元串被定義需要“(”和“)”作為字首和字尾

var fctStr1 = 'function a() {}'

var fctStr2 = '(function a() {})'

var fct1 = eval(fctStr1)  // return undefined

var fct2 = eval(fctStr2)  // return a function