本小课题我们讨论三个问题
(1)对象函数和普通函数的区别;
(2)对象函数里面的this到底是谁;
(3)对象绑定(apply和call)。
1.3.1 对象函数和普通函数的区别
简单说,对象函数和普通函数的区别就是函数内有没有this关键字。这个我们不举例子了,因为下一个课题就是this是谁的问题。
1.3.2 对象函数的this是谁?
this是谁,简单说就是当前对象,那么当前对象是谁,谁点这个函数,谁就是这个函数的当前对象,没人点,当前对象分两种情况,strict模式下是window全局对象,非strict模式下是undefined。上例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script>
//'use strict'
var name = "MyWindow";
var age = 999;
function SayHello() {
alert("我是" + this.name + ",今年" + this.age+"岁了。");
}
var zhangsan = {
name: "张三",
age: 26,
ZhangsanSayHello: function () {
alert("我是" + this.name + ",今年" + this.age+"岁了。");
},
SayHello2:SayHello
}
zhangsan.ZhangsanSayHello(); //毫无疑问,this是zhangsan
zhangsan.SayHello2(); //对象zhangsan点的,this是zhangsan
SayHello(); //strict模式下是undefined,非strict模式是window
//window.SayHello(); //strict模式下调用方法
var fn = zhangsan.ZhangsanSayHello;
fn() //strict模式下是undefined,非strict模式是window
//window.fn() //strict模式下调用方法
</script>
</head>
<body>
</body>
</html>
既然找个对象这么费劲,还容易找错了,为了安全,在调用对象函数时全都显示指明对象最安全了,哪怕是window的。
我们知道了this是谁,我们看下一个问题。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script>
'use strict'
var name = "MyWindow";
var age = 999;
var zhangsan = {
name: "张三",
age: 26,
ZhangsanSayHello: function () {
function SayHelloInner() {
alert("我是" + this.name + ",今年" + this.age+"岁了。");
}
SayHelloInner();
}
}
zhangsan.ZhangsanSayHello();
</script>
</head>
<body>
</body>
</html>
非strict下,结果是window的name和age,strict模式下,报错。
这就尴尬了,指明对象了啊为啥还跑到全局了啊。因为SayHelloInner函数没指定对象。解决方案如下。
因为this指向的对象可变,那么,我们如果把this指向的变量固定下来不久解决问题了。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script>
// 'use strict'
var name = "MyWindow";
var age = 999;
var lisi = {
name: "李四",
age: 36,
}
var zhangsan = {
name: "张三",
age: 26,
ZhangsanSayHello: function () {
var that = this;
function SayHelloInner() {
alert("我是" + that.name + ",今年" + that.age+"岁了。");
}
SayHelloInner();
var that = lisi;
SayHelloInner();
}
}
zhangsan.ZhangsanSayHello();
</script>
</head>
<body>
</body>
</html>
这段代码中,我们不用this调用变量,而是把对象固定好,比如that和objLisi,这样this就乱不了,当然代码灵活度降低了。
当然,代码灵活度和可控性并不是不可调和,下一节的对象绑定就是解决对象是谁的问题。
1.3.3 对象绑定
apply和call就是控制this指向的。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script>
'use strict'
var name = "MyWindow";
var age = 999;
var lisi = {
name: "lisi",
age:36
}
var zhangsan = {
name: "张三",
age: 26,
ZhangsanSayHello: function () {
function SayHelloInner() {
alert("我是" + this.name + ",今年" + this.age+"岁了。");
}
SayHelloInner.apply(this);
}
}
zhangsan.ZhangsanSayHello(); //this时zhangsan
var fn = zhangsan.ZhangsanSayHello;
fn.apply(lisi); //this时lisi
fn.call(this); //this是全局对象window
fn.call(window); //见到this就害怕,可以显示指定window
</script>
</head>
<body>
</body>
</html>