一、问题的由来
为什么同一个函数运行时,结果不一样?
obj.foo()在obj环境执行,
foo()在全局环境中执行,
解释原理,理解this的作用
var f = function() {
// 上下文环境如何, this如何
console.log(this.x);
}
//小优化技巧:如果key和value一样时,则可以省略属性名
var obj = {
f, // f: f,允许在函数体内部,引用当前环境的其他变量
x:2
}
var x = 1; // window 全局
f();
//console.log(obj.f);
obj.f();
//一个语言内存空间的分配是怎样的
// 函数作为一个属性的值是函数地址
运行结果:怎么会不同呢?
二、内存的数据结构
【背景知识】{ a:1,b:2 } => HashMap哈希表
不同的数据结构会对应不同的内存分配方式。
【正文】
“JavaScript 语言之所以有this的设计,跟内存里面的数据结构有关系。”
跟传统语言的this不一样,面向对象中this还有另外的意义。
- 先回答一波:this是函数运行时约定的,函数的的内存分配方式(下面三会讲,内存分配过程中浏览器会将函数具体内容键/值对存在堆中,该过程会单独分配内存空间,然后把地址给栈中的相关属性变量)使其只要被其他人获得地址就可以在任何环境被调用,this就是为了确定这个环境的!
- 上一张内存中各种存放情况的图,其中可以看出通过函数地址可以在不同环境中使用它:(来自https://blog.csdn.net/Wayne1998/article/details/80458439)
- 与普通对象不同,函数可以调用外部的自己未定义的变量,所以也导致了this的出现!
对象创建过程
var obj = {foo: 5};
(不同数据结构会对应不同的分配方式)
- 右边先执行, 生成一个对象,存储在内存中,地址给obj,引用是通过地址发生的
obj.foo过程(过程发生了什么)
- 引擎chrome v8 , 先从变量obj 拿到内存地址 ,从该地址读取原始的对象, 再从该对象中返回foo属性中的value值
( 如果属性是函数呢?毕竟上面这些普通变量好像压根不需要this来帮助吧 ?!)
三、函数(重点)
var f = function { }; // 函数
var obj = {foo: f}; // 属性为函数
属性的值也可能是一个函数(上面的属性值是基本类型字面量)
再往下指了,
- 引擎 Chrome v8 给函数单独地分配内存空间,
将地址给变量foo属性的值。
函数是一个单独的值( 它不需要依赖对象也可以自己执行,如 f() ),它可以在不同的环境(上下文)执行。
故需要一个this来确定当前的上下文。否则会出现混淆。
四、环境变量
为什么要有上下文环境?
JS允许在函数体内部,引用当前环境的其他变量
var x = 1;
var f = function () {
console.log(x);
};
var f1 = function() {
var x = 1;
console.log(x);
};
var obj = {
x: 1;
f: function() {
console.log(x);
需要 this 来指定上下文环境
}
}
块级作用域 函数作用域 全局作用域,
由于可能会存在与不同的地域,所以需要this来帮助我们明确当前的上下文环境。
为什么需要this?
因为函数很greedy(是一个吃着碗里的,吃着锅里的家伙),它除了要用自己的变量,还想访问其他环境里的变量。
如果要去访问到其他的环境里的变量时,可以通过this来表示当前的上下文环境 (上下文环境就是函数本身环境上面一层的环境)
【小结】其他语言中this只是用于做面向对象,但在js中this有了新的角色,可以用于指向当前的运行环境,用于访问其他环境中的变量。
关键词:变量分配,地址的引用,函数的红杏出墙;