函数是一个可以被调用和执行任意次的程序片段。JavaScript函数是参数化的:函数的定义会包括一个称为形参的标识符列表,这些参数在函数体中像局部变量一样工作。函数调用会为形参提供实参的值。函数使用它们实参的值来计算返回值。函数使用它们实参的值来计算返回值,成为该函数调用表达式的值。除了实参之外,每次调用还会拥有另一个值——本次调用的上下文——这就是this关键字的值。
如果函数挂载在一个对象上,作为对象的一个属性,就称它为对象的方法。当通过这个对象来调用函数时,该对象就是此次调用的上下文。也就是该函数的this的值。用于初始化一个新创建的对象的函数称为构造函数。
函数声明语句“被提前”到外部脚本或外部函数作用域的顶部,所以以这种方式声明的函数,可以被在它定义之前的代码所调用。不过,以表达式声明的函数就另当别论了,为了调用一个函数,必须要能引用它,而是用一个以表达式方式定义的函数之前,必须把它赋值给一个变量。变量的声明提前了,但给变量赋值是不会提前的,所以,以表达式方式定义的函数在定义之前无法调用。
根据ECMAScript3和非严格的ECMAScript5对函数调用的规定,调用上下文(this的值)是全局对象。然而在严格模式下,调用上下文则是undefined。
函数和方法的区别:函数是普通定义的函数,而方法则是对象的函数属性。
函数调用和方法调用有一个重要的区别,即调用上下文。属性访问表达式由两部分组成,一个对象和属性名称。在这种调用方式中,对象成为调用上下文,函数体可以使用关键字this引用对象。
this是一个关键字,Javascript语法不允许对this赋值。
方法链:当方法的返回值是一个对象,这个对象还可以再调用它的方法。这种方法调用序列中(通常称为“链”或“级联”)每次的调用结果都是另外一个表达式的组成部分。当方法并不需要返回值时,最好返回this。如果在设计API中一直采用这种方式(每个方法都返回this),使用API就可以进行“链式调用”风格代码的编程,在这种编程风格中,只要指定一次要调用的对象即可,余下的方法都可以给予此进行调用。
和变量不同,关键字this没有作用域的限制,嵌套的函数不会从调用它的函数中继承this。如果嵌套函数作为方法调用,其this的值指向调用它的对象。如果嵌套函数作为函数调用,其this的值指向调用它的对象。如果嵌套函数作为函数调用,其this值不是全局对象(非严格模式下)就是undefined(严格模式下)。很多人误以为调用嵌套函数时this会指向调用外层函数的上下文。如果你想访问这个外部函数的this值,需要将this的值保存在一个变量里,这个变量和内存函数都同在一个作用域内。通常用self来保存this,eg:深入理解this上下文的切换
1)首先看程序的运行结果:
2)然后跟踪js解析执行的过程:变量声明提前
3)变量赋值
4)函数执行
5)第一个相等判断
6)执行到函数内部
那为什么此处this发生了变换呢?我们可以这样理解,函数是一个程序片段,一旦执行完,没用的东西就由GC(垃圾回收)收回,当执行内部嵌套函数时,首先执行子函数中函数定义,变量声明语句,一旦发现父级的变量在子函数中仍然被调用,则有一个变量重新指向父函数中变量的地址,然后清理父级变量对原有资源(包括变量和函数)的引用,最后只剩下子函数中引用的全局变量被报保留(这就是闭包),因此这时就相当于子函数裸漏在外边,因此也就很容易为什么此时this指向Window了。