js this 问题
发布于 9 年前 作者 bingqingwu 4007 次浏览 最后一次编辑是 8 年前 来自 问答

文件test.js内容如下:

var fruit = "apple";
function test(){
	console.log(this.fruit);
}
test();
//console.log(this);

执行 node test.js, 结果为 “undefined”. 修改 var fruit = “apple”; ==> this.fruit = “apple”, 结果为 “undefined”. 修改 var fruit = “apple”; ==> fruit = “apple”, 结果为 “apple”. 如果理解这三种定义的不同? test函数外的this 和 函数内的this 有何不同?

7 回复

This如果没调用者都指全局,我这么理解。node中你的文件好像不是全局。。珍爱生命使用use strict… 自豪地采用 CNodeJS ionic

node module 实际上是被包含在一个匿名函数中的,上下文并不是全局,搜一下 require 的工作原理。有很多介绍。 var fruit 是一个局域变量,没有主体。不加 var 那是不科学的,会出乱子。 这样的代码太没道理,直接 console.log(fruit) 就是了。为何要加个 this ,纯添乱不是。

var fruit是定义局部,this.fruit是当前context. 直接fruit是在global里,不你使用. 直接test()是传递一个为{}的context.要传递其他的context,可以test.call({fruit:‘hello’});

console.log(this)研究一下呀

// `node test.js` 这种方式执行的代码的`this`被绑定到了一个非global的对象
console.log(this === global);// false

// 下面这样的定义会在当前的词法环境中创建一个标识符引用, 或者说, 变量
// var fruit = "apple"; 
// 下面这样的赋值语句给当前this所绑定的对象中添加一个fruit属性
// this.fruit = "apple"
// 下面这种表达式会在global对象中添加一个属性fruit
// fruit = "apple";

function test(){
  console.log(this === global);// true
}
// 执行的时候没有给this绑定任何值, 那么默认 `this` 绑定的就是 `global`
test();

@William17 回答挺详细的!这个就是个执行上下文的问题,多琢磨琢磨,搞清楚原理,就比较容易了。node文件应该也是一层context

针对问题做的自我总结: 在node里,js的顶层对象是global; 在global上定义的属性和函数,在任何模块里都可以访问;

	这样的写法,fruit就成为global对象上定义的属性,其它模块可以通过 fruit 或 global.fruit 访问到:
	fruit = "apple"; 

.

	这两种写法是等效的 this === exports;  这时的fruit就成为模块对象exports上的属性:
	this.fruit = "apple";
	exports.fruit = "apple";

.

定义局部变量:
var fruit = "apple"; 

.

	如果是在test.js模块内调用test(), 则this === global:
	fruit = "banana";	//必须这样定义, 相当于: global.fruit;
	function test(){
		console.log("fruit: ", this.fruit);	//则this === global;
	}
	test();

.

	如果是在另外一个模块内,调用test.js 内的test方法,则其使用的是对象module.exports, 所以 this === exports:
	this.fruit = "orange";
	function test(){
		console.log("fruit: ", this.fruit);	//this === exports;
	}
	exports.test = test;
	这样外部模块即可以访问到 test函数又可以访问到fruit属性。
	所以,实际使用时应该使用局部变量,外部模块只能通过方法来访问内部变量:
	var fruit = "apple";
	function test(){
		console.log("fruit: ", fruit);
	}
	exports.test = test;
回到顶部