在一个对象中绑定函数,称为这个对象的方法
在JavaScript中,对象的定义是这样的
var xiaoming = { name: '小明', birth: 2000 };
但是,如果我们给xiaoming绑定一个函数,就可以做更多的事情
比如,写个age()方法,返回xiaoming的年龄
var xiaoming = {
name: '小明',
birth:2000,
age: function ()
{
var y = new Date().getFullYear()- this.birth;
return y ;
}
};
xiaoming.age; // function xiaoming.age()
xiaoming.age(); //20
绑定到对象上的函数称为方法,和普通函数也没啥区别,这个我们也在上一节提到过了,当然是避免和其他的全局变量冲突,所以没有定义到window,定义到了xiaoming上
但是它在内部使用了一个this关键字,这个this也是javascript内比较重要的概念
在一个方法内部,this是一个特殊变量,它始终指向当前对象,也就是xiaoming这个变量
所以,this.birth可以拿到xiaoming的birth属性
function getAge() {
var y = new Date().getFullYear()- this.birth; return y ; }
var xiaoming = { name: '小明', birth: 2000, age: getAge };
xiaoming.age;//function getAge()
xiaoming.age();//20
getAge();//NaN
调用xiaoming的方式没问题,但是单独调用函数getAge()却返回NaN,这就涉及到了this的指向
this的指向视情况而定,如果以对象的方法形式调用,比如xiaoming.age(),该函数的this指向被调用的对象,也就是xiaoming
如果单独调用函数,比如getAge(),此时,该函数的this指向全局对象,也就是window
如果这么写
var fn = xiaoming.age;// // 先拿到xiaoming的age函数
fn();//NaN
也是不行的
要保证this指向正确,必须用obj.xxx()的形式调用
在strict模式下函数的this指向undefined
'use strict';
var xiaoming =
{
name: '小明',
birth: 2020,
age: function ()
{ return new Date().getFullYear() - this.birth; } };
var fn = xiaoming.age
fn();//TypeError: Cannot read property 'birth' of undefined
修改一下
'use strict';
var xiaoming = {
name: '小明',
birth: 1990,
age: function () {
function getAgeFromBirth()
{ return new Date().getFullYear() - this.birth; }
return getAgeFromBirth(); } };
xiaoming.age();
TypeError: Cannot read property 'birth' of undefined
又报错了,原因是this指针只在age方法的函数内指向xiaoming,在函数内部定义的函数,this又指向undefined了(在非strict模式下,它重新指向全局对象window)
所以this只有在对象的方法函数里才指向对象,方法函数里的函数都指向window(strcit下undefiend)
那我们如何修复呢
我们用一个that变量首先捕获this
'use strict';
var xiaoming = {
name: '小明',
birth: 2000,
age: function ()
{ var that = this;
function getAgeFromBirth() { return new Date().getFullYear() - that.birth; }
return getAgeFromBirth(); } };
xiaoming.age();//20
在xiaoming的方法函数里首先就把this用that捕获了,然后在方法函数里定义的函数如果需要指向对象就用that即可
apply
虽然在一个独立的函数调用中,根据是否是strict模式,this指向undefined或window,不过,我们还是可以控制this的指向
要指定函数的this指向哪个对象,可以用函数本身的apply方法,它接收两个参数,第一个参数就是需要绑定的this变
量,第二个参数是Array,表示函数本身要传入的参数
用apply修复getAge()调用
function getAge()
{ return new Date().getFullYear() - this.birth; }
var xiaoming = {
name: '小明',
birth: 2000,
age: getAge };
xiaoming.age(); //20这个毫无疑问是对的
getAge.apply(xiaoming, []);
getAge.apply(xiaoming);//20
两种写法都可以,只需要传入xiaoming作为绑定的this对象,因为这个函数无参
另一个与apply()类似的方法是call(),唯一区别是
apply()把参数打包成Array再传入
call()把参数按顺序传入
通过具体例子看看吧
Math.max.apply(null, [3, 5, 4]); // 5
Math.max.call(null, 3, 5, 4); // 5
getAge.call(xiaoming);//20
对普通函数调用,我们通常把this绑定为null
利用apply(),我们还可以动态改变函数的行为
JavaScript的所有对象都是动态的,即使内置的函数,我们也可以重新指向新的函数
现在假定我们想统计一下代码一共调用了多少次parseInt()
最佳方案是用我们自己的函数替换掉默认的parseInt()
var count = 0;
var oldParseInt = parseInt;//保存我们的parseInt
parseInt=function(){
count+=1;
return oldParseInt.apply(null,arguments);}
parseInt('1')
1
parseInt('2')
2
parseInt('1312')
1312
parseInt('5634')
5634
count
4
其实this挺复杂的…最开始第一遍我也没太理解
也就是现在模模糊糊的理解了
strict模式下,一般的this指向undefined,而非strict模式下,this指向window
只有在什么情况下this会指向对象呢,就是在对象的方法函数内,而且就只限于方法函数,方法函数的内部函数this也指向undefined
那为什么需要this呢
你可能也觉得很麻烦,确实,时不时要考虑这个this绑定的是不是我们需要的对象,这很繁琐
直接把this指明成xiaoming,什么事情也没有
var xiaoming = {
name: '小明',
birth: 2000,
age: function ()
{
function getAgeFromBirth() { return new Date().getFullYear() - xiaoming.birth; }
return getAgeFromBirth(); } };
xiaoming.age();//20
var getAge=function(){return new Date().getFullYear() -xiaoming.birth;}
var xiaoming = {
name: '小明',
birth: 2000,
age: getAge}
xiaoming.age();//20
这样确实可以解决问题,但是这样带来的坏处就是不灵活
javascript是面向对象编程,特别是之后开发的时候,可能这个函数需要适用到需要变量上,这样写明显是不灵活的
但如果我们添加了this这个概念,只需要在使用每个函数修改一下指向,这样不大大提升了整体代码的灵活度吗,而且也可以防止我们写串了,这样调用函数是无法干扰其他对象的,划清了界限,也提高了我们整体的容错率