JS函数调用
Javascript 函数有 4 种调用方式。每种方式的不同在于this的初始化。
this关键字
一般而言,在Javascript中,this指向函数执行时的当前对象。但是this是保留关键字,并不能被修改。
调用函数,函数中的代码在函数被调用后执行。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <title></title> 6 <script> 7 function myFunction(a, b) { 8 return a * b; 9 } 10 myFunction(10, 2); //myFunction(10, 2) 返回20 11 </script> 12 </head> 13 </html>
以上函数不属于任何对象,但是在JS中它始终默认是全局对象。
在HTML中默认的全局对象是HTML页面本身,所以函数是属于HTML页面的。
在浏览器中的页面对象是浏览器窗口。以上函数会自动变为window对象的函数。
所以myFunction()与window.myFunction()是一样的效果。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <title></title> 6 <script> 7 function myFunction(a, b) { 8 return a * b; 9 } 10 window.myFunction(10, 2); //返回20 11 </script> 12 </head> 13 </html>
这个是调用JS函数常用的方法,但不是良好的编程习惯。
全局变量、方法和函数容易造成命名冲突的bug。
全局对象:
当函数没有被自身的对象调用时,this的值就会变成全局对象。在浏览器中全局对象是window对象。所以以下代码this值返回window对象。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <title></title> 6 <script> 7 function myFunction() { 8 return this; 9 } 10 window.myFunction(); //返回windo对象 11 </script> 12 </head> 13 </html>
函数作为全局对象调用,会使this的值变成全局对象。使用window对象作为一个变量容易造成程序崩溃。
函数作为方法进行调用:
在JS中可以将函数定义为对象的方法。
以下一段代码创建了一个对象myObject,对象有两个属性firstName和lastName,以及一个方法fullName:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title></title> <script> function myObject() { firstName:'前端'; lastName:'技术'; fullName:function() { return this.firstName + " " + this.lastName; } } myObjec.fullName(); //返回前端 技术 </script> </head> </html>
fullName方法是一个函数。函数属于对象。myObject是函数的所有者。
this对象拥有javascript代码。以上代码中this的值为myObject对象。
以下代码修改了fullName方法并返回this值:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title></title> <script> function myObject() { firstName:'前端'; lastName:'技术'; fullName:function() { return this; } } myObjec.fullName(); //返回[object object](所有者对象) </script> </head> </html>
函数作为对象方法调用,会使得 this 的值成为对象本身。
使用构造函数调用函数:
如果函数调用前使用了new关键字,则调用了构造函数。
看起来就像创建了新的函数,但实际上JS函数是重新创建的对象:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <title></title> 6 <script> 7 function myFunction(arg1, arg2) { 8 this.firstName = arg1; 9 this.lastName = arg2; 10 } 11 12 // This creates a new object 13 var x = new myFunction("前端","技术"); 14 x.firstName; // 返回 "前端" 15 </script> 16 </head> 17 </html>
构造函数的调用会创建一个新的对象。新对象会继承构造函数的属性和方法。
构造函数中this关键字没有任何的值。
this的值在函数调用时实例化对象的时候创建。
作为函数方法调用函数:
在JS中,函数是对象。JS函数有它的属性和方法。
call()和apply()是预定义的函数方法。两个方法可用于调用函数,两个方法的第一个参数必须是对象本身。
call方法:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <title></title> 6 <script> 7 function myFunction(a, b) { 8 return a * b; 9 } 10 myFunction.call(myObject, 10, 2); // 返回 20 11 </script> 12 </head> 13 </html>
apply方法:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title></title> <script> function myFunction(a, b) { return a * b; } myArray = [10,2]; myFunction.apply(myObject, myArray); // 返回 20 </script> </head> </html>
两个方法都使用了对象本身作为第一个参数。 两者的区别在于第二个参数: apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入,而call则作为call的参数传入(从第二个参数开始)。
在 JS严格模式(strict mode)下, 在调用函数时第一个参数会成为 this 的值, 即使该参数不是一个对象。
在 JS 非严格模式(non-strict mode)下, 如果第一个参数的值是 null 或 undefined, 它将使用全局对象替代。
通过 call() 或 apply() 方法可以设置 this 的值, 且作为已存在对象的新方法调用。