面对对象(四)对象的方法中this

CodePathfinderX
• 阅读 704

var obj ={
foo: function () {

console.log(this);

}
};

obj.foo() // obj
上面代码中,obj.foo方法执行时,它内部的this指向obj。
但是,下面这几种用法,都会改变this的指向。

// 情况一
(obj.foo = obj.foo)() // window
// 情况二
(false || obj.foo)() // window
// 情况三
(1, obj.foo)() // window
上面代码中,obj.foo就是一个值。这个值真正调用的时候,运行环境已经不是obj了,而是全局环境,所以this不再指向obj。

可以这样理解,JavaScript 引擎内部,obj和obj.foo储存在两个内存地址,称为地址一和地址二。obj.foo()这样调用时,是从地址一调用地址二,因此地址二的运行环境是地址一,this指向obj。但是,上面三种情况,都是直接取出地址二进行调用,这样的话,运行环境就是全局环境,因此this指向全局环境。上面三种情况等同于下面的代码。

上面三种情况等同于下面的代码。

// 情况一
(obj.foo = function () {
console.log(this);
})()
// 等同于
(function () {
console.log(this);
})()

// 情况二
(false || function () {
console.log(this);
})()

// 情况三
(1, function () {
console.log(this);
})()

2.this所在的方法不在对象的第一层(一个函数一层)

这时this只是指向当前一层的对象,而不会继承更上面的层

var a = {
p: 'Hello',
b: {

m: function() {
  console.log(this.p);
}

}
};

a.b.m() // undefined
上面代码中,a.b.m方法在a对象的第二层,该方法内部的this不是指向a,而是指向a.b,因为实际执行的是下面的代码。

var b = {
m: function() {
console.log(this.p);
}
};

var a = {
p: 'Hello',
b: b
};

(a.b).m() // 等同于 b.m()

var a = {
b: {

m: function() {
  console.log(this.p);
},
p: 'Hello'

}
};

var hello = a.b.m;
hello() // undefined
上面代码中,m是多层对象内部的一个方法。为求简便,将其赋值给hello变量,结果调用时,this指向了顶层对象。为了避免这个问题,可以只将m所在的对象赋值给hello,这样调用时,this的指向就不会变。

var hello = a.b;
hello.m() // Hello

点赞
收藏
评论区
推荐文章
巴拉米 巴拉米
4年前
bind、call、apply 区别?如何实现一个bind?
一、作用call、apply、bind作用是改变函数执行时的上下文,简而言之就是改变函数运行时的this指向那么什么情况下需要改变this的指向呢?下面举个例子var name"lucy";const obj{    name:"martin",    say:function (){        co
待兔 待兔
11个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
LinMeng LinMeng
4年前
Object.keys()详解
Object.keys():遍历对象的所有属性,该方法返回一个数组,数组内容就是对象的所有键名。传入对象,返回属性名varobj{'a':'meng','b':'lin'}console.log(Object.keys(obj));//'a','b'varobj{100:"a",2:"b",7:"c"};cons
Aidan075 Aidan075
4年前
宁可用python倒读红楼梦,也不向拼多多低头
↑一个宝藏公众号,有趣的不像个技术号刚屏蔽了天猫的盖楼,没想到大家把拼多多链接玩出了花样李大伟你可看好了!我一定要退订!主要用到python中列表的 insert() 方法list.insert(index, obj)其中参数obj: 要插入列表中的对象;index:对象obj需要插入的索引位置。方法就是将字符串中的
Wesley13 Wesley13
3年前
Java并发 wait()、notify()和notifyAll()
一个线程修改一个对象的值,而另一个线程则感知到了变化,然后进行相应的操作,这就是wait()、notify()和notifyAll()方法的本质。具体体现到方法上则是这样的:一个线程A调用了对象obj的wait方法进入到等待状态,而另一个线程调用了对象obj的notify()或者notifyAll()方法,线程A收到通知后从对象obj的wait方法返回,继续
Stella981 Stella981
3年前
JavaScript 学习笔记八 继承与引用
functionlogs(obj){document.write(obj"<br/");}//打印log日志//继承//继承可以通过原型链来实现//解释器会在对象中查找该属性,如果//没有找到,则在其内部对象prototype对象上搜索,由于prototype对象与对象本身的结/
Stella981 Stella981
3年前
Javascript 监听简单对象的属性变化
//简单对象的属性的变化监控//通过setAttr改变属性的值var o  {  'a':2,  'b':3};function watch(obj, attr, callback){   if(typeof obj.defaultValues  'undefine
Wesley13 Wesley13
3年前
Velocity的模板中访问公有成员变量
velocity模板中的访问对象属性,对于POJO对象来说,必须符合JavaBean的规范,也就是${obj.xxx}这样的访问会转换到obj.getXxx()这个方法的调用上。对于一些需要直接访问公用成员变量的对象(比如obj中直接有xxx变量),就不行了。官方配置文档(https://www.oschina.net/action/GoTo
Wesley13 Wesley13
3年前
ES6
JavaScript定义对象的属性,有两种方法。varobj{foo:true,abc:123};上面代码的方法一是直接用标识符作为属性名,方法二是用表达式作为属性名,这时要将表达式放在方括号之内。但是,如果使用字面量方式定义对象(使用大括号),在ES5中只能使用方法
Stella981 Stella981
3年前
Javascript中创建函数的几种方法
//工厂函数模式//无法解决对象识别问题functionperson0(name,age,job){varobjnewObject();obj.namename;obj.ageage;obj.jobjob;returno
Stella981 Stella981
3年前
Javascript定义类(class)的三种方法
在面向对象编程中,类(class)是对象(object)的模板,定义了同一组对象(又称"实例")共有的属性和方法。Javascript语言不支持"类",但是可以用一些变通的方法,模拟出"类"。一、构造函数法这是经典方法,也是教科书必教的方法。它用构造函数模拟"类",在其内部用this关键字指代实例对象。  function