pomelo源码分析--node.js中的this

作者:[email protected],转载请注明作者

在继续分析代码之前,需要先讲一下node.js中的this是什么。因为不讲这个的话,后面的内容进行不下去。在以前版本的node.js中,全局this是个空对象,在node8的repl中,全局this和global是相等的。

> this === global
true

1
2
3
但是,如果使用node8执行js文件,全局this是个空对象。

console.log(this)
let result = this === global
console.log(result)
执行结果:
{}
false
1
2
3
4
5
6
好,这个很操蛋的事实还是要接受的。node.js中的this和浏览器中的this又是不一样的。忘掉在浏览器中的经验吧,只要记得this只能随着函数走就行了。为了不影响三观,后面的js语句都只能在文件中写好,然后再用node去执行它。

在C++/java中,this永远都是和某个对象相关的,this生存在类作用域中,隐式存在着。但是在node.js中,它的行为很是诡异。

一、在普通函数中的this,实际上是在引用global,如果你不相信,就执行一下下面的代码。记得先保存文件,然后再执行文件。

function fn(){
  this.num = 10;
}
fn();
console.log(this); {}
console.log(this.num); undefined
console.log(global.num); 10
1
2
3
4
5
6
7
二、this作用域是和函数紧密相关的。来看段稍微长一点的代码。

var name = "like global...";
function one() {
  var name = "in func one...";
  var other = "somewhat...";
  function two() {
    var name = "in func two...";
    console.log({name: name, other: other});
  }
  two();
  console.log({name: name, other: other});
}
one();
console.log({name: name});
console.log({other: other});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
这段代码是执行不了的,语法报错。执行环境node8,其它的环境也许能通过。在console.log({other:other})引用了函数one作用域里的other。都是不合法的。

那什么情况是合法的,只有引用作用域内的才合法。

var name = "like global...";
function one() {
  var name = "in func one...";
  var other = "somewhat...";
  function two() {
    var name = "in func two...";
    console.log({name: name,other:other });
  }
  two();
  console.log({name: name, other: other});
}
one();
console.log({name: name});
1
2
3
4
5
6
7
8
9
10
11
12
13
代码证明,同名变量可以在不同作用域存在,不同作用域引用同名变量得到的值不同。也就是存在作用域同名变量覆盖的情况。

三、“构造函数”的this指向的是它自己,而不是global。

function Person(name,age) {
    this.name = name;
    this.age = age;
}

let p1 = new Person("lilei", 50);
let p2 = new Person("hanmeimei",45);

console.log(p1);
console.log(p2);
console.log(global.name);
console.log(global.age);
1
2
3
4
5
6
7
8
9
10
11
12
四、this魔幻走位,上面看的例子都还好理解,下面来一个让人觉得很诡异的例子。

let Person = {
    name : "sam",
    age : 18,
    foo: function() {
        console.log(this.name + ",how old are you?", this.age);
    }
};

let Pet = {
    name : "dog",
    age : 3,
    foo : Person.foo
};

Pet.foo();

输出结果为
dog,how old are you? 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
惊喜不惊喜,意外不意外?name和age前不加this是执行不了的,因为作用域问题。但是加上以后呢,为什么输出的和java/c++中的完全不一样。原因就是this是随着执行上下文发生改变的。ecma5提供了一个bind方法,bind可以指定一个this参数,以确保函数在执行的时候,里面的this永远是bind时的那个this,而不会随着调用上下文发生变化。

最后总结一下:

1.在js中,创建一个作用域的唯一方法就是使用function关键字。for循环,case之类的都不行。这和c++/java是不一样的。

2.var声明的变量在整个当前域都是有效的,而且它会覆盖外部同名变量。

3.this和arguments是随着代码调用位置的变化而变化的。每个嵌套层次切换时都发生变化。
--------------------- 
作者:心中那自由的世界 
来源:CSDN 
原文:https://blog.csdn.net/119365374/article/details/77609091 
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自blog.csdn.net/Allen_Walker_QAQ/article/details/86642796