22.JavaScript对象中的方法、this关键字

对象中的方法

之所以在编程思想中引入面向对象,是因为面向对象的思维方式更适合处理真实世界中的实体关系。程序中的每个对象都对应着真实世界中的实体,是实体的抽象表达形式。

例如,我们可以使用以下代码表示一个小朋友:

let child = {
	name:'Tom',
	age:8,
	height:70,
	weight:30,
}

这个小朋友姓名叫Tom,年龄8岁,身高70cm,体重30kg

这看起啦很完美,但是,真实世界中的小朋友除了具备以上这些基本属性之外,还有很多行为属性,比如蹦、跳、吃、喝、唱歌等待。

如何在对象中表示实体的行为呢?这就是本文的重点:对象方法

《函数表达式》章节,我们就知道了函数可以存储在变量中,所以我们可以把实体的行为封装成函数,然后存储在对象的变量中。

对象方法

我们可以使用方法表示对象的行为特征,例如:

let child = {
	name:'Tom',
	age:8,
};
child.sing = function(){
	console.log('I am a happy boy~~')
}

代码执行结果如下:

> let child = {
  	name:'Tom',
  	age:8,
  };
  child.sing = function(){
  	console.log('I am a happy boy~~')
  }
< ƒ (){
  	console.log('I am a happy boy~~')
  }
> child.sing()
< I am a happy boy~~

这里我们使用函数表达式创建了一个函数,并把函数赋值给child对象的sing属性。
随后,我们就可以通过调用child.sing()方法,实现小朋友的唱歌行为啦。

对象方法的调用和调用属性差不多,不过在尾部添加了(),我们还可以使用方括号调用方法:

child['sing']();//效果是一样哒

对象方法的写法

  1. 方法预定义
    除了上述的对象方法编写方式之外,我们还可以使用预定义函数的方式:

    let child = {
    	...
    }
    function sing(){
    	console.log('I am a happy boy~~');
    }
    child.sing = sing;	//添加方法
    child.sing();		//调用方法
    
  2. 方法简写
    以上方式稍显繁琐,可以简单一点

    let child = {
    	name:'Tom',
    	sing:function(){
    		console.log('I am a happy boy~~');
    	}
    };
    
  3. 更加简写的方式

我们可以像简写对象属性的方式一样,使用方法名作为键名:

let child = {
	sing(){
		console.log('I am a happy boy~~');
	}
};

以上几种方法在用途上几乎是没有区别的,除了在继承方面稍有区别,后面会详细介绍,这里还是能简则简。

对象中的 this

对象中的方法通常需要访问对象中的其他属性,因为动作(对象的方法)通常不是平白无故发生的,例如拿东西就需要用手,而手就是对象的一个属性。

举个例子:

let xiaoming = {
	name:'xiaoming',
	age:8,
	sayHello:function(){
		console.log(`My name is ${this.name}`);
	}
};
xiaoming.sayHello();

代码执行结果如下:

> let xiaoming = {
  	name:'xiaoming',
  	age:8,
  	sayHello:function(){
  		console.log(`My name is ${this.name}`);
  	}
  };
  xiaoming.sayHello();
< My name is xiaoming

以上代码中的sayHello属性是对象xiaoming中的一个方法,方法中使用了对象的另外一个属性name。这种情况下,就需要使用一个新的关键字thisthis的值就是当前使用它的函数所在的对象实例,此处就是xiaoming这个对象本身。

单纯的从实现输出name属性值的角度上来讲,还可以使用对象名调用的方式:

let xiaoming = {
	name:'xiaoming',
	age:8,
	sayHello:function(){
		console.log(`My name is ${xiaoming.name}`);//这里的this改为了对象名xiaoming
	}
};
xiaoming.sayHello();

控制台执行以上代码,二者输出并无差别:

> let xiaoming = {
  	name:'xiaoming',
  	age:8,
  	sayHello:function(){
  		console.log(`My name is ${xiaoming.name}`);//这里的this改为了对象名xiaoming
  	}
  };
  xiaoming.sayHello();
< My name is xiaoming

既然二者并无明显区别,为什么要使用this而不是直接使用对象名称呢?

可以通过现实生活中的场景解释这个问题:小明向别人介绍自己的名字,会说:“你好,我的名字是小明”,而不是说:“你好,小明的名字是小明”。在上面的代码中,this.name就是指自己的名字,xiaoming.name就是指小明的名字。

使用this在编程过程中,还能规避一些隐藏的逻辑缺陷。

举个例子:

let xiaoming = {
	name:'xiaoming',
	age:8,
	sayHello:function(){
		console.log(`My name is ${xiaoming.name}`);//错误,不能执行
	}
};

let xiaohong = xiaoming;//复制一个变量
xiaoming = null;
xiaohong.sayHello();

以上代码是无法执行的,因为xiaoming赋值为null,而null没有name属性就会引发异常。
如果把xiaoming.name替换为this.name就完全没有问题了。

这里的介绍可能过于潜伏,实际上,面向对象是一门高深的学问,其中涉及对象、实例、属性和方法。
有一套完整的理论逻辑运行其中,但javascrpt的this不同于其他面向对象语言的this指针。
下面会详细介绍其中的区别,此处只需要记住,访问对象中的属性用this。

函数的this

JavaScript中,this关键字(注意这里不是this指针),和其他大多数面向对象语言都是不同的。

JavaScriptthis关键字可以用于任何函数之中,即使这个函数不是对象的函数:

function sayHello(){
	console.log(this.name);
}

用过JavaC++等语言的童鞋可能会诧异,但以上代码在JavaScript中没有任何问题。

JavaScript语言中的this是在代码执行过程中计算出来的,取决于调用方法的上下文。

其他面向对象的语言,this指针通常是绑定的,在代码还没执行的时候就已经确定了它的值只能是特定对象的实例。

也就是说,谁调用有this的函数,函数中的this就指向谁。

举个例子:

let xiaoming = {name:'XiaoMing'};
let xiaohong = {name:'XiaoHong'};
function sayHello(){
	console.log(this.name);
}
xiaoming.sayHello = sayHello;
xiaohong.sayHello = sayHello;
xiaoming.sayHello();
xiaohong.sayHello();

代码的执行结果:

> let xiaoming = {name:'XiaoMing'};
  let xiaohong = {name:'XiaoHong'};
  function sayHello(){
  	console.log(this.name);
  }
  xiaoming.sayHello = sayHello;
  xiaohong.sayHello = sayHello;
  xiaoming.sayHello();
  xiaohong.sayHello();
<  XiaoMing
<  XiaoHong

以上代码非常容易理解,xiaoming.sayHello()中的this就是xiaomingxiaohong.sayHello()中的this就是xiaohong

肯定有好奇的童鞋就问了,如果我们定义了一个函数不适用对象调用,而是直接指向,会出现什么呢?

举个例子:

function sayHello(){
	alert(this);
}

如果我们直接在控制台调用上述函数,那么就会得到一个window对象。
use strict模式下调用上述函数,就会得到undefined

函数中有this关键字通常意味着它会被对象调用,如果我们编写一个函数不是在对象中调用,同时又包含this,那么多半是程序出错了。

悲惨的箭头函数(lambda)

箭头函数比较悲惨,它们没有属于自己的this。如果我们在箭头函数中使用this,那么this的取值就取决于外部的“常规函数”。

举个例子:

let user = {
	name:'xiaoming',
	sayHello:()=>{
		alert(this.name);
	}
}
user.sayHello();

这段代码什么都不会输出~~

如果需要在箭头函数中使用this,需要在函数中调用它:

let user = {
	name:'xiaoming',
	sayHello:function(){
		let f = ()=>{
			alert(this.name);
		}
		f();
	}
}
user.sayHello();

总结

  1. 对象可以使用方法表示实体的一些动作性属性
  2. 方法调用使用.,类属于obj.func()
  3. 方法可以使用this引用对象
  4. this是程序执行过程中计算出来的,谁调用属于谁
  5. 对象可以相互复制
  • 24
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 27
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 27
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@魏大大

我们都没有打赏的习惯

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值