{"action":"opened","issue":{"url":"https://api.github.com/repos/Islion/islion.github.com/issues/1","repository_url":"https://api.github.com/repos/Islion/islion.github.com","labels_url":"https://api.github.com/repos/Islion/islion.github.com/issues/1/labels{/name}","comments_url":"https://api.github.com/repos/Islion/islion.github.com/issues/1/comments","events_url":"https://api.github.com/repos/Islion/islion.github.com/issues/1/events","html_url":"https://github.com/Islion/islion.github.com/issues/1","id":197469862,"number":1,"title":"JavaScript Ninjia revie","user":{"login":"Islion","id":22774281,"avatar_url":"https://avatars.githubusercontent.com/u/22774281?v=3","gravatar_id":"","url":"https://api.github.com/users/Islion","html_url":"https://github.com/Islion","followers_url":"https://api.github.com/users/Islion/followers","following_url":"https://api.github.com/users/Islion/following{/other_user}","gists_url":"https://api.github.com/users/Islion/gists{/gist_id}","starred_url":"https://api.github.com/users/Islion/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Islion/subscriptions","organizations_url":"https://api.github.com/users/Islion/orgs","repos_url":"https://api.github.com/users/Islion/repos","events_url":"https://api.github.com/users/Islion/events{/privacy}","received_events_url":"https://api.github.com/users/Islion/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2016-12-24T16:47:00Z","updated_at":"2016-12-24T16:47:00Z","closed_at":null,"body":"#JavaScript 忍者秘籍\r\n\r\n这本350页的书共15章，下面的文字大部分来自书中的摘要，另外还包括一些想法和疑问。\r\n\r\n##函数\r\n\r\n###函数是一等公民\r\nJavaScript是一门多范式语言，支持函数式编程。函数在JavaScript中是第一对象，不仅和普通JavaScript对象一样，可以被任意变量引用，或声明成对象字面量,甚至可以将函数作为参数传递。这是JavaScript富有表现力的原因之一。\r\n\r\n`\t\r\n\tarray.sort((v1,v2)=>v2-v1) //js排序算法\r\n`\r\n\r\n对象在JavaScript中拥有如下功能:\r\n\r\n* 可以通过字面量进行创建\r\n* 可以赋值给变量，数组或者其它对象属性\r\n* 可以通过参数传递给函数\r\n* 可以作为函数的返回值\r\n* 可以拥有动态创建并赋值的属性\r\n\r\n函数拥有以上全部功能，除此之外，函数还有一个特殊功能，它们可以被调用（invoked）\r\n\r\n###作用域\r\n与受C语言语法影响的语言不一样，大多数情况下，每一个代码块都会创建自己的作用域。但在JavaScript中并非如此。\r\n\r\n在JavaScript中，作用域是由function声明的，而不是代码块。声明的作用域创建于代码块，但不是终结于代码块。考虑下面的代码：\r\n\r\n```\r\n\tfunction foo(){\r\n\t\tif(true){\r\n\t\t\tvar x = 213\r\n\t\t}\r\n\t\tconsole.log(x)\r\n\t}\r\n\tfoo()//213\r\n```\r\n--\r\n\r\n事实上这样的设计存在很多问题。考虑下面的代码：\r\n\r\n```\r\n\tfunction foo(){\r\n\t\tvar a = 0\r\n\t\tfunction bar(){\r\n\t\t\tif(true){\r\n\t\t\t\tvar a\r\n\t\t\t}\r\n\t\t\ta=1\t\t\r\n\t\t}\r\n\t\tbar()\r\n\t\tconsole.log(a)\r\n\t}\r\n\tfoo()//0\r\n```\r\nES6的`let`、`const`很好的解决了这个问题\r\n\r\n##函数调用\r\n函数是如何被调用的对其内部代码的执行有着巨大的影响。尤其在this参数的创建中。\r\n\r\n函数有4种被调用的方式，每种都有自己的细微差别。\r\n\r\n* 作为一个函数进行调用，是最简单的形式\r\n* 作为一个方法进行调用，在对象上进行调用，支持面向对象编程\r\n* 作为构造器进行调用，创建一个新对象\r\n* 通过`apply``call`方法进行调用\r\n\r\n###实参到形参\r\n当一个参数列表作为函数调用的一部分时，这些参数会按照函数声明里的形参声明排序，将实参值分别赋值给这些形参。如果实参个数和形参个数不一样，不会抛错，JavaScript可以完美解决这种问题，具体策略如下。\r\n\r\n* 如果实参大于形参，超出部分不会分配给形参\r\n* 如果实参小于形参，未分配到的形参被赋值未undefined\r\n\r\n有趣的事情是，所有函数在被调用时都会传入2个隐式参数：`argument`和`this`**（ES6新增的箭头函数不会）**\r\n\r\n所谓隐式（implicit），也就意味着这些参数不会显示列在参数签名里，但是它们摸摸地传递给函数并存在于函数作用域内。在函数内部可以像其他显示命名的参数一样使用。\r\n####arguments\r\narguments是传递给函数形参的一个集合。该集合有一个length属性，其值是全部实参的个数。单个参数值可以像访问数组索引一样进行获取。\r\n\r\n--\r\n\r\n但是请注意，arguments并不是一个真正的数组，而是一个类数组。\r\n\r\n```\r\n\tfunction foo(){\r\n\t\tconsole.log(arguments)\r\n\t}\r\n\tfoo('Issac','Alan')\r\n\t\r\n\t/*\r\n\tArguments[2]\r\n\t0:'Issac'\r\n\t1:'Alan'\r\n\tcallee:foo()\r\n\tlength:0\r\n\tSymbol(Symbol.iterator):values()\r\n\t__proto__:Object //原型不是Array\r\n\t*/\r\n```\r\n我们可以通过带有副作用的`slice`函数将arguments转化为数组，考虑下面的代码。\r\n\r\n```\r\n\tfunction foo(){\r\n\t\treturn [].slice.call(arguments)\r\n\t}\r\n\tObject.prototype.toString.call(foo())//\"[object Array]\"\r\n```\r\n####this\r\nthis参数引用了与该函数调用进行隐式关联的一个对象，被称之为函数上下文（function context）\r\n\r\n函数上下文是一个概念，来自像Java这样的面向对象语言。面向对象语言认为,this是方法声明所在类的一个实例，它的指向依赖于类的声明。但是在JavaScript中，this的指向依赖于函数的调用。基于这个事实，我们将this称为调用上下文（invoked context）。根据函数的调用方式不同，this的指向也同。\r\n\r\n###作为函数进行调用\r\n最常见的调用方式，通常发生在函数上使用`()`操作符进行调用的时候。`()`操作符并没有将函数作为对象的一个属性。函数的上下文是全局上下文--window对象。下面是简单实例。\r\n\r\n```\r\n\tfunction foo(){}\r\n\tfoo()\r\n\tvar bar = foo(){}\r\n\tbar()\r\n```\r\n--\r\n\r\n‘函数作为函数’调用这种方式，实际上是作为方法调用的特殊情况（函数作为window的属性）这样的设计非常奇怪，它**没有**继承所处作用域的this指向，考虑下面的代码。\r\n\r\n```\r\n\tvar name = 'window'\r\n\tvar foo = {\r\n\t\tname:'foo',\r\n\t\tbar:function(){\r\n\t\t\t(function(){\r\n\t\t\t\tconsole.log(this.name)\r\n\t\t\t})()\t\r\n\t\t}\r\n\t}\r\n\tfoo.bar()//window\r\n```\r\n可见，内部立即执行匿名函数的this已经指向window。ES6新增的**箭头函数**修复了这个设计失误，考虑下面的代码。\r\n\r\n```\r\n\tvar name = 'window'\r\n\tvar foo = {\r\n\t\tname:'foo',\r\n\t\tbar:function(){\r\n\t\t\t(()=>{\r\n\t\t\t\tconsole.log(this.name)\r\n\t\t\t})()\t\r\n\t\t}\r\n\t}\r\n\tfoo.bar()//foo\r\n```\r\n\r\n###作为方法进行调用\r\n当函数被赋值给一个对象的属性，并使用引用该函数的这个属性进行调用时，那么函数就是作为该对象的一个方法进行调用。示例如下：\r\n\r\n```\r\n\tvar o = {}\r\n\to.foo=function(){}\r\n\t\r\n```\r\n\r\n\r\n"}}
{"actor":{"display_login":"Islion"}}