3.1 对象的方法
如果一个对象的属性值,是一个函数,我们称这个属性叫做这个对象的方法(methods)。
下面这个对象有一个属性叫做sayHello,它的值是一个匿名函数,所以我们把这个sayHello 叫做 obj 的方法。
我们用圆括号打点调用sayHello属性,这个属性的值是函数,所以就能圆括号执行。
3.2 函数的上下文
现在我们要研究的是函数的上下文(context),所谓的上下文就是指函数里面的 this 是谁。
当一个函数当做对象的方法被调用的时候,这个函数里面的 this 表示这个对象。
现在我们调用函数的时候,是通过obj打点调用的,所以现在这个 sayHello 函数的上下文就是 obj 对象,即 sayHello 函数内部的 this 指向 obj 。
但是,千万不要认为写在对象里面的函数,上下文一定是这个对象!
函数的上下文是什么,取决于函数怎么调用!而不是函数如何定义!
换句话说,函数的上下文是函数调用时表现的性质!不是函数定义的时候写死的性质!
3.3函数上下文五个规律
规律一:函数用圆括号调用,函数的上下文是window对象!
比如小题目:
函数function fun(){} 的上下文是什么!不要看它怎么定义,要看它怎么调用!!此时是 fun() 函数名加上圆括号直接调用,此时上下文就是window对象!
而我们知道,所有的全局变量都是 window 对象的属性(注意:函数里面的局部变量,不是window的属性,不是任何东西的属性,它就是一个变量!!)
规律二:函数如果作为一个对象的方法,对象打点调用,函数的上下文就是这个对象!
比如下面的例子,我们把fun函数定义出来了,然后又把这个函数绑定给了obj对象的c属性,
调用的时候是 对象.函数()
此时根据规律,函数里面的this 是这个对象,所以能够弹出10。
规律三:函数是事件处理函数,函数的上下文就是触发这个事件的对象
下面我们定义了一个fun,然后把这个fun当做了3个DOM元素的事件处理函数:
这个函数不会执行,直到用户点击了某个div 标签,此时点击谁,this就是谁!
规律四:定时器调用函数,上下文是window对象
函数fun被定时器调用,函数的上下文是window对象,每隔一秒钟弹出一次888。
做一个小例子吧,点击一个盒子,两秒钟之后变红:
上面这个程序是错误的,这是因为函数的最终调用者是定时器!所以函数的上下文是window对象,而window对象没有背景颜色。
怎么办?备份this!备份上下文!
在定时器外面的事件处理函数中,this 就是box1这个元素,此时我们可以备份上下文,把this存为局部变量self,后面的程序就用self 指代box1,还可以用_this 、that等等。
规律五:数组中存放的函数,被数组索引调用,this就是这个数组
比如:
此时这个函数是从数组中枚举出来然后加圆括号执行的,所以最终调用者可以认为是这个数组,上下文就是这个数组。
3.4 函数上下文小题目
题目1:
最终调用形式是对象.函数() 此时适用规律二,此时的 this 就是对象。
题目2:
正确答案是2,这是一个标准面试题。
我们现在讲解这个题目,首先说说什么是 arguments.callee ,在函数内部,如果想得到函数自身,用 this 是不可能的,我们必须使用arguments.callee
弹出 true,因为 arguments.callee 就是fun自己。
函数的length是什么呢?我们做一个小实验:
函数的length是形参列表的长度,就是函数定义的时候写在fun()圆括号里面的字母个数,无视你的实参个数!也就是说arguments.callee.length 就是形参列表的个数。
而 arguments.length 表示实参个数,就是调用函数的时候传进来的实参个数。
此时我们看看刚才的题目:
函数的最终调用,是 arguments 对象进行方括号索引得到的这个函数,然后加圆括号调用的,所以符合规律2或者规律5,如果你认为 arguments 是对象,此时规律2 生效,如果你认为 arguments 是数组,也没事,规律5生效,此时无论如何,函数 fun 里面的 this 是 arguments 对象!所以 arguments 对象 callee 属性就是 f() 函数,它的长度就是形参列表个数,答案是2。
如果换成this.length ,答案就是4!