如何理解及运用function

导语 Function作为Javascript的核心技术之一,清晰的理解function的机制和用法,对我们进行javascript开发非常重要。你有想过function是什么吗?ECMAScript 的函数实际上是功能完整的对象。其中function是javascript中
Function作为Javascript的核心技术之一,清晰的理解function的机制和用法,对我们进行javascript开发非常重要。你有想过function是什么吗?ECMAScript 的函数实际上是功能完整的对象。其中function是javascript中定义函数的关键字,由function定义的函数是一个由代码集合而成的对象,属于引用类型。而Function则是javascript中的引用类型中的一种,类似Number和String和Object和Boolean。Function类可以表示开发者定义的任何函数。
 
博学谷
 
 
Function与function
 
ECMAScript 最令人感兴趣的可能莫过于函数实际上是功能完整的对象。Function 类可以表示开发者定义的任何函数。
用 Function 类直接创建函数的语法如下:
 
var function_name = new function(arg1, arg2, ..., argN, function_body)
在上面的形式中,每个 arg 都是一个参数(最多 25 个),最后一个参数是函数主体(要执行的代码)。这些参数必须是字符串。
记得下面这个函数吗?
 
  1. function sayHi(sName, sMessage) { 
  2.   alert("Hello " + sName + sMessage); 
还可以这样定义它:
 
  1. var sayHi = new Function("sName""sMessage""alert(\"Hello \" + sName + sMessage);"); 
虽然由于字符串的关系,这种形式写起来有些困难,但有助于理解函数只不过是一种引用类型,它们的行为与用 Function 类明确创建的函数行为是相同的。
请看下面这个例子:
 
  1. function doAdd(iNum) { 
  2.   alert(iNum + 20); 
  3.  
  4. function doAdd(iNum) { 
  5.   alert(iNum + 10); 
doAdd(10); //输出 "20"
如你所知,第二个函数覆盖了第一个函数,使 doAdd(10) 输出了 “20”,而不是 “30”。
如果以下面的形式重写该代码块,这个概念就清楚了:
 
  1. var doAdd = new Function("iNum""alert(iNum + 20)"); 
  2. var doAdd = new Function("iNum""alert(iNum + 10)"); 
  3. doAdd(10); 
请观察这段代码,很显然,doAdd 的值被改成了指向不同对象的指针。函数名只是指向函数对象的引用值,行为就像其他对象一样。甚至可以使两个变量指向同一个函数:
 
  1. var doAdd = new Function("iNum""alert(iNum + 10)"); 
  2. var alsodoAdd = doAdd; 
  3. doAdd(10); //输出 "20"
  4. alsodoAdd(10); //输出 "20"
在这里,变量 doAdd 被定义为函数,然后 alsodoAdd 被声明为指向同一个函数的指针。用这两个变量都可以执行该函数的代码,并输出相同的结果 - “20”。因此,如果函数名只是
 
指向函数的变量,那么可以把函数作为参数传递给另一个函数吗?回答是肯定的!
 
  1. function callAnotherFunc(fnFunction, vArgument) { 
  2.   fnFunction(vArgument); 
  3.  
  4. var doAdd = new Function("iNum""alert(iNum + 10)"); 
  5.  
  6. callAnotherFunc(doAdd, 10); //输出 "20"
在上面的例子中,callAnotherFunc() 有两个参数 - 要调用的函数和传递给该函数的参数。这段代码把 doAdd() 传递给 callAnotherFunc() 函数,参数是 10,输出 “20”。
注意:尽管可以使用 Function 构造函数创建函数,但最好不要使用它,因为用它定义函数比用传统方式要慢得多。不过,所有函数都应看作 Function 类的实例。
如前所述,函数属于引用类型,所以它们也有属性和方法。
ECMAScript 定义的属性 length 声明了函数期望的参数个数。例如:
 
  1. function doAdd(iNum) { 
  2.   alert(iNum + 10); 
  3.  
  4. function sayHi() { 
  5.   alert("Hi"); 
  6.  
  7. alert(doAdd.length); //输出 "1"
  8. alert(sayHi.length); //输出 "0"
函数 doAdd() 定义了一个参数,因此它的 length 是 1;sayHi() 没有定义参数,所以 length 是 0。
记住,无论定义了几个参数,ECMAScript 可以接受任意多个参数(最多 25 个),这一点在上面讲解过。属性 length 只是为查看默认情况下预期的参数个数提供了一种简便方式。
Function 对象也有与所有对象共享的 valueOf() 方法和 toString() 方法。这两个方法返回的都是函数的源代码,在调试时尤其有用。例如:
 
  1. function doAdd(iNum) { 
  2.   alert(iNum + 10); 
  3.  
  4. document.write(doAdd.toString()); 
上面这段代码输出了 doAdd() 函数的文本。
 
function使用
  1. function myfunc(param) { 
  2.     //code
注意Javascript中的函数名相同的两个function被认为是同一个,在运行时到底调用哪一个function取决于加载顺序,后一个加载的function会覆盖前一个.
 
 
  1. function func1() {return 'func1'; } 
  2. function func1(name) { return name; } 
究其原因是:javascript中function的参数都是可选参数,因此funciton的识别是不包括入参的,而函数入参处的声明是为了引用方便以及可读性.
以上的代码也等价于:
 
  1. function func1() { 
  2.     return arguments[0] || 'func1'
  3. func();              //return 'func1'
  4. func('function'); //return 'function'
function当作对象
 
是的没错,在javascript中function就是对象,我们可以向使用一个对象那样使用function。它可以有自己的属性和方法.有如下的一个funciton:
 
  1. function nameOf(name) { 
  2.     return name.toUpperCase();  
  3. function作为对象进行赋值 
  4.  
  5. var person = person || {}; 
  6. person.nameOf = nameOf; 
  7. person.nameOf('yang dong'// return "YANG DONG"
定义function的属性
 
看看以下的代码, 你能从中的到什么信息:
 
  1. function nameOf() {return nameOf.blogger;} 
  2. nameOf.blogger = "YANG_DONG"
没错,function可以拥有自己的属性。考虑这样一种场景, 假如我们要统计某个function被调用的次数.那么我们有两种方式来实现:
 
1.设定一个全局变量来记录,该funciton被调用的次数,每调用一次,该变量加1:
 
  1. var globalNameOfCounter = 0; 
  2. nameOf(); 
  3. globalNameOfCounter ++; 
这样做看起来是没有问题的,在代码还是比较简单的时候,它可以工作的很好,但是随着代码越来越复杂,维护这段逻辑的成本会直线上升。主要是因为:globalNameOfCounter污染的global命名空间,并且破坏了代码的封装性.
 
2.使用function的属性
看看以下代码:
 
  1. function nameOf() { 
  2.     nameOf.counter++; 
  3.     return nameOf.blogger; 
  4. nameOf.blogger = “YANG_DONG" 
  5. nameOf.counter = 0;   
  6. nameOf(); //nameOf.counter = 1
  7. nameOf(); //nameOf.counter = 2
显而易见,第二种方式有着很好的封装性和维护性.function的属性的应用还不止如此.请看下文.
 
function作为名字空间
 
Javascript不支持名字空间(本人不太理解如此强大的语言为什么不支持名字空间呢,这是为什么呢?),
 
不过我们依然可以使用其强大的funciton为我们支持名字空间.
 
从上节我们知道function可以定义自己的属性,我们就可以利用该特性来生成名字空间.请看以下代码:
 
  1. nameOf.getBloggerName = function() { 
  2.     return nameOf.blogger; 
此时在nameOf名字空间之下已经包含了:blogger,counter属性和function getBloggerName.
 
function作为method
 
在javascript中function和method其实是没有什么本质区别的,如果非的区分两者的话,我想也就是this变量不同吧.
 
  1. function g() {return this;} 
  2. var local = local || {}; 
  3. local.method = g; //修改this指向local
  4. local.method();   //返回local对象
  5. g();              //返回DOMWindow对象
function皆为closure
 
在Javascript中所有的function都绑定了一个scope chain,因此它是一个保存了调用上下文的函数.看看下面的实例代码:
 
  1. var variable = 'global'
  2. function getVariable(){ 
  3.     var variable = 'local'
  4.     func = function() { 
  5.         return variable; 
  6.     }; 
  7.     return func; 
  8. getVariable()();  //return local;
当func被调用的时候,它所取的varible的值是调用上下文中的变量而并非与之同名的全局变量.
 
总结
 
如果用一句话概括今天对funciton的介绍,那么我想应该是: function是可以被调用执行的代码集对象.
 
以上是function的一些应用场景,当然它还不止这些.
 
比如: function作为构造函数(也就是funciton作为类),继承等.这些内容将在以后大家介绍,敬请期待.
 

 
Function对象的属性和方法
 
函数是 JavaScript 中的引用数据类型,在函数这个对象上定义了一些属性和方法,下面我们逐一来介绍这些属性和方法,这对于理解Javascript的继承机制具有一定的帮助。
 
属性(Properties)
 
arguments
 
获取当前正在执行的 Function 对象的所有参数,是一个类似数组但不是数组的对象,说它类似数组是因为其具有数组一样的访问性质及方式,可以由arguments[n]来访问对应的单个参数的值,并拥有数组长度属性length。还有就是arguments对象存储的是实际传递给函数的参数,而不局限于函数声明所定义的参数列表(length),而且不能显式创建 arguments 对象。下面的Sample说明了这些性质。
 
  1. function testArg(a, b) { 
  2.     var actCount = arguments.length, 
  3.         expCount = testArg.length, 
  4.         result; 
  5.  
  6.     result = "Expected arguments' count is " + expCount + ";<br/>"
  7.     result += "Actual arguments' count is " + actCount + ".<br/>"
  8.     result += "They are:<br/>"
  9.     for (var i = 0; i < actCount; i++) { 
  10.         result += arguments[i] + ";<br/>"
  11.     } 
  12.     if (arguments instanceof Array) { 
  13.         result += "arguments is an Array instance."
  14.     } else if (arguments instanceof Object) { 
  15.         result += "arguments is an Object instance."
  16.     } 
  17.     document.write(result); 
  18. testArg(1); 
  19. //output result is:
Expected arguments' count is 2;
Actual arguments' count is 1.
They are:
1;
arguments is an Object instance.
####length
获取函数定义的参数个数,functionName.length
不同于arguments.length,这点我们在上面有介绍。因为Javascript调用函数时候对函数参数不作任何个数和类型检查,也就没有函数调用错误概念。但是我们可以利用functionName.length和arguments.length的不同,在函数调用内部来检测参数个数检测。
 
  1. function checkVarCount(a, b) { 
  2.     if (checkVarCount.length !== arguments.length) { 
  3.         alert("The count of the parameters you passed into the function doesn't match the function definition."); 
  4.     } 
  5.     alert("Successfully call the function"); 
  6. checkVarCount(1, 2); 
  7. //Successfully call the function
  8. checkVarCount(1); 
  9. //The count of the parameters you passed into the function doesn't match the function definition.
caller获取调用当前函数的函数。caller属性只有当函数正在执行时才被定义。
 
functionName.caller
如果函数是从 JavaScript 程序的顶层调用的,则caller包含null。如果在字符串上下文中使用 caller 属性,则其结果和 functionName.toString 相同,也就是说,将显示函数的反编译文本。
 
  1. function test() { 
  2.     if (test.caller == null) { 
  3.         document.write("test is called from the toppest level"); 
  4.     } else { 
  5.         document.write("test is called from the function:<br/>"); 
  6.         document.writeln(test.caller.toString()); 
  7.     } 
  8.     document.write("<br />"); 
  9. //call from the top level
  10. test(); 
  11. //output: test is called from the toppest level
  12.  
  13. function testOuter() { 
  14.     test(); 
  15.  
  16. //call from the function testOuter
  17. testOuter(); 
  18. //output:
  19. //test is called from the function:
  20. //function testOuter() { test(); }
  21. ####callee
返回正被执行的 Function 对象,即指定的 Function 对象的正文。
 
 
[functionName.]arguments.callee
callee 属性是 arguments 对象的一个成员,该属性仅当相关函数正在执行时才可用。通常这个属性被用来递归调用匿名函数。
 
  1. var fac = function(n){ 
  2.   if (n <= 0) 
  3.      return 1; 
  4.   else
  5.      return n * arguments.callee(n - 1); 
  6. }(4); 
  7. document.write(fac);//24
constructor
 
获取创建某个对象的函数。constructor 属性是每个具有原型的对象的原型成员。 这包括除 Global 和 Math 对象之外的所有内部 JavaScript 对象。 constructor 属性就是用来构造对象实例的函数引用。
 
  1. // A constructor function.
  2. function MyObj() { 
  3.     this.number = 1; 
  4.  
  5. var x = new String("Hi"); 
  6.  
  7. if (x.constructor == String) 
  8.     document.write("Object is a String."); 
  9. document.write ("<br />"); 
  10.  
  11. var y = new MyObj; 
  12. if (y.constructor == MyObj) 
  13.     document.write("Object constructor is MyObj."); 
  14.  
  15. // Output:
  16. // Object is a String.
  17. // Object constructor is MyObj.
prototype获取对象的原型。每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。这意味着,我们可以把那些不变的属性和方法,直接定义在prototype对象上。
 
 
  1. function Man(name, age) { 
  2.     this.name = name; 
  3.     this.age = age; 
  4. Man.prototype.sex = "M"
  5. Man.prototype.struggle = function () { 
  6.     alert("day day up!!!!"); 
  7. var li = new Man("Leo", 10); 
  8. alert(li.sex);//M
  9. li.struggle();//day day up
  10. Man.prototype.isStrong = true
  11. alert(li.isStrong);//true
  12. 这样我们也可以向已定义好的对象(包括javascript提供的原生对象)中追加方法和属性, 
  13.  
  14. var aa = new Number(2); 
  15. alert(typeof (aa.add)); //undefined
  16. Number.prototype.add = function (add1) { 
  17.     return this + add1; 
  18. alert(aa.add(1)); // 3
方法 apply调用函数,并用指定对象替换函数的this值,同时用指定数组替换函数的参数。
 
functionName.apply([thisObj[,argArray]])
如果argArray为无效值,则会抛出”Object expected”错误;如果thisObj和argArray都没有提供,则会使用当前this作为thisObj
 
  1. function callMe(arg1, arg2) { 
  2.     var s = ""
  3.  
  4.     s += "this value: " + this
  5.     s += "<br />"
  6.     for (i in callMe.arguments) { 
  7.         s += "arguments: " + callMe.arguments[i]; 
  8.         s += "<br />"
  9.     } 
  10.     return s; 
  11.  
  12. document.write("Original function: <br/>"); 
  13. document.write(callMe(1, 2)); 
  14. document.write("<br/>"); 
  15.  
  16. document.write("Function called with apply: <br/>"); 
  17. document.write(callMe.apply(3, [4, 5])); 
  18. document.write("<br/>"); 
  19.  
  20. document.write("Function called with apply with invalid array: <br/>"); 
  21. try
  22.     document.write(callMe.apply(3,2)); 
  23. catch (e) { 
  24.     document.write(e.message); 
  25. document.write("<br/><br/>"); 
  26.  
  27. document.write("Function called with apply without any argument: <br/>"); 
  28. document.write(callMe.apply()); 
  29. //Output result:
  30. //Original function:
  31. //this value: [object Window]
  32. //    arguments: 1
  33. //    arguments: 2
  34.  
  35. //Function called with apply:
  36. //this value: 3
  37. //    arguments: 4
  38. //    arguments: 5
  39.  
  40. //Function called with apply with invalid array:
  41. //Function.prototype.apply: Arguments list has wrong type
  42.  
  43. //Function called with apply without any argument:
  44. //this value: [object Window]


call调用一个对象的方法,用另一个对象替换当前对象。
 
call([thisObj[, arg1[, arg2[, [, argN]]]]])
它允许您将函数的 this 对象从初始上下文变为由 thisObj 指定的新对象。 如果没有提供 thisObj 参数,则 global 对象被用作 thisObj。与apply方法唯一不同的地方是,apply的
 
第二个参数类型必须是Array,而call方法是将所有的参数列举出来,用逗号分隔。
 
 
  1. function callMe(arg1, arg2){ 
  2.     var s = ""
  3.  
  4.     s += "this value: " + this
  5.     s += "<br />"
  6.     for (i in callMe.arguments) { 
  7.         s += "arguments: " + callMe.arguments[i]; 
  8.         s += "<br />"
  9.     } 
  10.     return s; 
  11.  
  12. document.write("Original function: <br/>"); 
  13. document.write(callMe(1, 2)); 
  14. document.write("<br/>"); 
  15.  
  16. document.write("Function called with call: <br/>"); 
  17. document.write(callMe.call(3, 4, 5)); 
  18.  
  19. // Output:
  20. // Original function:
  21. // this value: [object Window]
  22. // arguments: 1
  23. // arguments: 2
  24.  
  25. // Function called with call:
  26. // this value: 3
  27. // arguments: 4
  28. // arguments: 5
bind
 
对于给定函数,创建具有与原始函数相同的主体的绑定函数。 在绑定功能中,this对象解析为传入的对象。 该绑定函数具有指定的初始参数。
 
function.bind(thisArg[,arg1[,arg2[,argN]]])
其中function, thisArg为必选项。返回一个与 function 函数相同的新函数,只不过函数中的this对象和参数不同。
 
  1. // Define the original function.
  2. var checkNumericRange = function (value) { 
  3.     if (typeof value !== 'number'
  4.         return false
  5.     else
  6.         return value >= this.minimum && value <= this.maximum; 
  7.  
  8. // The range object will become the this value in the callback function.
  9. var range = { minimum: 10, maximum: 20 }; 
  10.  
  11. // Bind the checkNumericRange function.
  12. var boundCheckNumericRange = checkNumericRange.bind(range); 
  13.  
  14. // Use the new function to check whether 12 is in the numeric range.
  15. var result = boundCheckNumericRange (12); 
  16. document.write(result); 
  17.  
  18. // Output: true
以下代码演示如何使用 arg1[,arg2[,argN]]] 参数。 该绑定函数将 bind 方法中指定的参数用作第一个参数和第二个参数。 在调用该绑定函数时,指定的任何参数将用作第三个、第四个参数(依此类推)。
 
 
  1. // Define the original function with four parameters.
  2. var displayArgs = function (val1, val2, val3, val4) { 
  3.     document.write(val1 + " " + val2 + " " + val3 + " " + val4); 
  4.  
  5. var emptyObject = {}; 
  6.  
  7. // Create a new function that uses the 12 and "a" parameters
  8. // as the first and second parameters.
  9. var displayArgs2 = displayArgs.bind(emptyObject, 12, "a"); 
  10.  
  11. // Call the new function. The "b" and "c" parameters are used
  12. // as the third and fourth parameters.
  13. displayArgs2("b""c"); 
  14. // Output: 12 a b c
在对象定义内部使用bind方法可以将某个事件绑定到对象内部的某个方法,
 
  1. <input type="button" id="start" value="Start" /> 
  2. <input type="button" id="stop" value="Stop" /> 
  3. <script type="text/javascript"
  4.     function Car(owner) { 
  5.         this.owner = owner; 
  6.         this.start = function () { 
  7.             //start the car
  8.             console.log(this); 
  9.             //output: Car {owner: "Mike", start: function, stop: function} check.html:14
  10.             console.log(this.owner + "'s car is starting."); 
  11.             //output: Mike's car is starting.
  12.         }; 
  13.         this.stop = function () { 
  14.             console.log(this); 
  15.             //output: <input type="button" id="stop" value="Stop" />
  16.             console.log(this.owner + "'s car is starting."); 
  17.             //output: undefined's car is stopping.
  18.         }; 
  19.     } 
  20.     var btnStart = document.getElementById("start"), 
  21.         btnStop = document.getElementById("stop"), 
  22.         someCar = new Car("Mike"); 
  23.  
  24.     if (document.attachEvent) { 
  25.         btnStart.attachEvent("onClick", someCar.start.bind(someCar)); 
  26.         btnStop.attachEvent("onClick", someCar.stop); 
  27.     } else if (document.addEventListener) { 
  28.         btnStart.addEventListener("click", someCar.start.bind(someCar), false); 
  29.         btnStop.addEventListener("click", someCar.stop, false); 
  30.     } 
  31. </script> 
从上面Sample我们发现,当不使用bind方法的时候,事件里面的this指向的触发click事件dom元素input,它当然没有owner属性;如果利用bind指定事件里面的this对象,就能达到我们想要的效果。
 
toString返回对象的字符串表示形式。
 
objectname.toString([radix])
objectname必需,指定需要获取字符串表示形式的对象。radix可选,为将数字值转换为字符串指定一个基数,此值仅用于数字。
 
toString 方法是一个所有内置的 JavaScript 对象的成员。 它的行为取决于对象的类型:
 
Object Behavior
Array 将 Array 的元素转换为字符串。 结果字符串被连接起来,用逗号分隔。
Boolean 如果布尔值为 true,则返回“true”。 否则返回“false”。
Date 返回日期的文本表示形式。
Error 返回一个包含相关错误信息的字符串。
Function 返回如下格式的字符串,其中 functionname 是一个函数的名称,此函数的 toString 方法被调用:
function functionname( ) { [native code] }
 
Number 返回数字的文字表示形式。
String 返回 String 对象的值。
Default 返回 "[object objectname]",其中 objectname 为对象类型的名称。
valueOf
 
返回对象的原生值。
 
 
object.valueOf( )
Javascript内部各个对象定义的valueOf不同:
 
Object Return value
Array  返回数组实例。
 Boolean  布尔值。
 Date  从 UTC 1970 年 1 月 1 日午夜开始的存储的时间值(以毫秒为单位)。
 Function  函数本身。
 Number  数字值。
 Object  对象本身。 这是默认值。
 String  字符串值。
Math 和 Error 对象都没有 valueOf 方法。
总结
 
Function 和 function,理解了吗?
https://www.nucmc.com/ true 如何理解及运用function https://www.nucmc.com/show-12-800-1.html report 24244.5 Function作为Javascript的核心技术之一,清晰的理解function的机制和用法,对我们进行javascript开发非常重要。你有想过function是什么吗?ECMAScript 的函数实际上是功能完整的对象。其中function是javascript中
TAG:function
本站欢迎任何形式的转载,但请务必注明出处,尊重他人劳动成果
转载请注明: 文章转载自:BETWAY官网网 https://www.nucmc.com/show-12-800-1.html
BETWAY官网网 Copyright 2012-2014 www.nucmc.com All rights reserved.(晋ICP备13001436号-1)