JavaScript tips:Function调用模式对this的影响
近来,学习了一下《JavaScript精粹》,读到了函数这章,理清了JavaScript中this在不同调用模式下的指向。
1、Function调用模式:Function是JavaScript的一种引用类型,拥有四种调用模式:方法调用模式,函数调用模式,构造器调用模式,apply(call, bind)调用模式
2、Function的不同调用模式对this产生不同的影响:
(1)方法调用模式:Function作为对象的方法被调用。此时,this指向调用Function的对象。
1 var obj = { 2 name: "lucy", 3 printName: function( ) { 4 console.log( this.name ); // 此时printName,作为obj的方法被调用,this指向调用printName的obj,this.name === "lucy"。 5 } 6 };
(2)构造器调用模式:Function作为构造器被调用,亦即使用new操作符,创建新的对象实例,并且将this指向新创建的对象实例;同时,执行构造器内的代码为新的对象实例添加成员,最后返回这个新的对象实例。
1 // 创建构造器Demo,在Demo被new操作符调用时,this指向Demo的prototype。 2 var Demo = function( ){ 3 this.name = "jack"; 4 }; 5 6 // 在Demo的prototype中,添加方法printName。 7 Demo.prototype.printName = function( ){ 8 console.log(this.name); 9 }; 10 11 // 创建Demo实例,此时this已经指向Demo的prototype 12 var d = new Demo( ); 13 console.log(d.name); // 在控制台输出"jack" 14 d.printName( ); // 在控制台输出"jack"
PS:构造函数、构造器只是在英译中的过程中的翻译用词差异,在英文都是constructor。《JavaScript精粹》译为构造器,《JavaScript高级程序设计》第三版译为构造函数。
(3)apply(call, bind)调用模式:JavaScript中,函数也是对象而具有方法,其具有方法apply。apply接受两个参数,第一个是要传递给this的值,第二个是参数数组。当函数调用apply方法时,将函数内部的this指向apply传递的第一个参数。
1 var people = { 2 this.name = "lily"; 3 } 4 5 var printName = function( ){ 6 console.log(this.name) 7 } 8 9 // 此时apply将this指向了people 10 printName.apply(people) // 在控制台输出 lily
PS:《JavaScript精粹》中只提及apply。apply和call在功能上是相同的,但是具体的使用方式上,有小差异。
(4)函数调用模式:既不是作为方法调用,也不是调用自己的apply(call, bind),也不是作为构造器被new调用,这时候调用就是函数调用模式。此时函数内部的this指向全局变量,在浏览器中指的是window变量,在node.js中指的是global变量。
1 window.name = "bob"; 2 3 // 此时this指向window 4 var printName = function( ) { 5 console.log( this.name ); 6 }; 7 8 console.log(window.name) // 在控制台输出bob 9 printName() // 在控制台输出bob
以setTimeout(callback, time)为例:
1 window.name = "bush"; 2 3 // 在全局作用域 4 setTimeout(function( ){ 5 console.log(this.name); // 在控制台输出"bush" 6 }, 100); 7 8 // 在对象方法内部 9 var obj = { 10 name : "trump", 11 printName : function( ){ 12 var _this = this; 13 setTimeout(function( ){ 14 console.log(_this.name); // 在控制台输出"trump" 15 console.log( this.name ); // 在控制台输出"bush" 16 }, 1000); 17 } 18 }; 19 obj.printName();
3、小结:
(1)方法调用模式:this指向调用方法的对象。
(2)构造器调用模式:this指向构造器的创建的实例对象。
(3)apply调用模式:this指向apply传入的第一个对象。
(4)函数调用模式:this指向全局对象window(node中指向global)。