{"action":"closed","issue":{"url":"https://api.github.com/repos/rockcoder23/blog.fexnotes.com/issues/9","labels_url":"https://api.github.com/repos/rockcoder23/blog.fexnotes.com/issues/9/labels{/name}","comments_url":"https://api.github.com/repos/rockcoder23/blog.fexnotes.com/issues/9/comments","events_url":"https://api.github.com/repos/rockcoder23/blog.fexnotes.com/issues/9/events","html_url":"https://github.com/rockcoder23/blog.fexnotes.com/issues/9","id":99881626,"number":9,"title":"javascript函数调用中this变量","user":{"login":"rockcoder23","id":7693969,"avatar_url":"https://avatars.githubusercontent.com/u/7693969?v=3","gravatar_id":"","url":"https://api.github.com/users/rockcoder23","html_url":"https://github.com/rockcoder23","followers_url":"https://api.github.com/users/rockcoder23/followers","following_url":"https://api.github.com/users/rockcoder23/following{/other_user}","gists_url":"https://api.github.com/users/rockcoder23/gists{/gist_id}","starred_url":"https://api.github.com/users/rockcoder23/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rockcoder23/subscriptions","organizations_url":"https://api.github.com/users/rockcoder23/orgs","repos_url":"https://api.github.com/users/rockcoder23/repos","events_url":"https://api.github.com/users/rockcoder23/events{/privacy}","received_events_url":"https://api.github.com/users/rockcoder23/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/rockcoder23/blog.fexnotes.com/labels/javascript","name":"javascript","color":"bfe5bf"},{"url":"https://api.github.com/repos/rockcoder23/blog.fexnotes.com/labels/Shit%20Done","name":"Shit Done","color":"159818"}],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2015-08-09T10:18:18Z","updated_at":"2015-08-09T10:28:43Z","closed_at":"2015-08-09T10:28:43Z","body":"最近看道大师的 javascript：The Good part一书中谈道在javascript中函数的调用的四种方式，今天就来说说这四种不同方式下的this变量的含义。以下代码建议在chrome下运行。\r\n\r\n#### 1. 函数的方法调用模式\r\n\r\n当function作为对象的属性调用时，我们称之为方法。看以下代码结果。\r\n```js\r\nvar myObject = {\r\n    value: 0,\r\n    increment: function(inc){\r\n        // console.log(typeof inc);  //返回表示数据类型的字符串。\r\n        // console.log(typeof inc === 'number') //inc 如果是number类型，则输出true；\r\n        console.log(this);//谁调用this 指向谁。输出myObject对象\r\n        this.value += typeof inc === 'number' ? inc : 1;\r\n    }\r\n};\r\nmyObject.increment();\r\nconsole.log(myObject.value); //1\r\nmyObject.increment(2);\r\nconsole.log(myObject.value); //3\r\nmyObject.increment('0');\r\nconsole.log(myObject.value); //4\r\n```\r\n可见，在函数作为对象的属性时，被调用时this指向这个对象。\r\n\r\n#### 2. 函数的函数调用模式\r\n\r\n当函数并非一个对象的属性时，那它就当做一个函数来调用。\r\n```js\r\nmyObject.double = function(){\r\n    console.log(this); //myObject\r\n    console.log(\"outter function's this: \" + this); //myObject\r\n    var helper = function(){\r\n        //绑定到了全局的对象window；\r\n        console.log(\"inner function's this: \" + this); //window\r\n    }\r\n    helper();\r\n};\r\nmyObject.double();\r\n```\r\n我们为myObject增加一个double方法，并且在double方法中定义了一个helper函数，并调用它。我们可以可以看到这个时候，第一个输出的this指向myObject，原理跟第一个一样。然而，helper函数里面的this却指向了window全局对象。正如道大师所说这是javascript设计中的一个错误。为了能让内嵌的函数能访问包裹它的函数的上下文，我们可以如下设计。\r\n\r\n//利用js函数闭包可以访问上一层的函数的上下文的特性。\r\n//把对象本身赋值给变量that。这样就实现了对外层函数的操作。\r\n```js\r\nmyObject.double = function(){\r\n    var  that = this;\r\n    var helper = function(){\r\n        console.log(that.value);\r\n        that.value = that.value + 1;\r\n        console.log(that.value);\r\n    }\r\n    helper();\r\n};\r\nmyObject.double();\r\n```\r\n我们习惯上把包裹函数的this对象赋值给that，利用javascript闭包的特性，就可以使用内嵌函数访问包裹函数的上下文。这个特性经常会用到。\r\n\r\n#### 3. 函数的构造器调用模式\r\n\r\n如果一个函数的创建是为了让new调用，那么这个函数成为构造器，当用new调用时，会创建一个新对象，并且这个对默认链接到这个构造器的prototype属性的对象上。见如下代码：\r\n```js\r\nvar Quo = function(string){\r\n    console.log(\"inner constructor this: \");\r\n    console.log(this);\r\n    this.status = string;\r\n    console.log(this);\r\n}\r\n\r\n//给所有从Quo构造的对象添加get_status方法。\r\nQuo.prototype.get_status = function(){\r\n    console.log(\"inner get_status this: \");\r\n    console.log(this);\r\n    return this.status;\r\n};\r\nvar myQuo = new Quo(\"confused..\");\r\nconsole.log(\"myQuo.get_status: \" + myQuo.get_status());\r\n```\r\n这个时候构造器内的this指向了新创建的对象。\r\n\r\n#### 4. 函数的apply调用模式\r\n\r\napply方法让我们构建一个参数数组传递给调用函数，它也允许我们选择this的值，apply方法接收两个参数，第一个是要绑定给this的值，第二个就是一个参数数组；\r\n```js\r\nvar status_Object = {\r\n    status: 'A-OK'\r\n};\r\n\r\n//status_Object 并没有继承自Quo.prototype，但我们可以在status_Object\r\n//调用get_status方法。\r\nvar status = Quo.prototype.get_status.apply(status_Object);\r\nconsole.log(status);\r\n```\r\n结合第三种调用方式中的代码，可以看出，因为get_status方法的参数为空，所以我们只传入了status_Object，从输出（get_status方法内的输出）可见this指向了status_Object。但当apply()的参数为空时，默认调用全局对象。"}}