什么是“本”之前的对象在JS实例?(What is 'this' before an

2019-09-23 23:34发布

我不明白以下几点:

var x = function() {
    this.foo="foo";
    return function() {
        this.bar = "bar";
        return foo+bar;
    };
}(); // returns inner

alert(x()); // 'foobar', so both 'this' variables are set
alert(x.bar); // undefined - but wasn't it used correctly?
alert(new x().bar); // ok, works

我的假设是,一个默认“这个”范围/可变地图被生成并用来在第一时间,然后当“新”被调用时,一个新的对象(功能?)和一个新的“本”是通过发送和返回。 或者,也许x不是一个合适的对象? 不过,如何“这个”最终会被设置和使用,使“foobar的”?

我需要什么,知道的明白这一点?

Answer 1:

首先,让我们来看一些细微之处的JavaScript的,那么我们就可以处理你的榜样。

函数的上下文

误解的一点是上下文。 每个函数被调用的情况下,这是可以使用关键字this 。 让我们写我们可以用它来检查上下文的功能:

var probe = function(){
  // if the context doesn't have a name, let's name it
  if(!this.name){
    this.name = "lumberjack";
  }
  // print the name of my context
  console.log(this.name);
};

开始了:

name = "global!";

// when we call a function normally it still have a context:
// the global context
probe(); // prints: global!

var ctx = {name: "ctx"};

// we can set a context explicitly using call()
probe.call(ctx); // prints: ctx

// we can set a context explicitly using apply()
probe.apply(ctx); // prints: ctx

// it is set implicitly, if we call a function as a member
ctx.fun = probe;
ctx.fun(); // prints: ctx

// or we can create a brand new object and set it as a context:
// that's what "new" does
var t = new probe(); // prints: lumberjack

// let's sum it up:
console.log(name);     // prints: global!
console.log(ctx.name); // prints: ctx
console.log(t.name);   // prints: lumberjack

这就是为什么它是很容易陷入困境,并在不经意间下降至全球范围。

在构造函数返回值

很多人感到困惑,当他们看到一个构造函数返回值。 它是合法的。 构造函数可以返回一个对象,功能,或阵列。 该值将被用作一个实例。 旧实例将被丢弃。

var myClass = function(){
  // if it is called as a constructor, "this" will be a new instance
  // let's fill it up:
  this.a = 42;
  this.b = "Ford";
  this.c = function(){ return "Perfect"; };
  // done? let's discard it completely!
  // and now for something completely different...
  return {
    owner: "Monty Python",
    establishment: "Flying Circus"
  };
};
var t = new myClass();
alert(t.owner + "'s " + t.establishment);

正如预期的那样显示“Monty Python的飞行马戏团”。

如果一个构造函数返回别的东西(例如,数字,字符串,空,未定义)返回的结果将被丢弃,旧实例将被使用。

这个例子

你举的例子是很难理解的,主要是因为它是书面的方式。 让我们通过重写简化它。

首先让我们来处理x

var x = function() {
  this.foo = "foo";
  return function() {
    this.bar = "bar";
    return foo + bar;
  };
}(); // returns inner

正如我们所看到的匿名函数(第1 function )立即执行的,所以我们可以内联它:

// next assignment can be simplified because
// top "this" is window or the global scope
//this.foo = "foo"; =>
foo = "foo";
x = function() {
  this.bar = "bar"; // this line depends on its context, or "this"
  return foo + bar; // this line uses global "foo" and "bar"
};

所以在最后,我们有两个全局变量: foo (串)和x (函数)。

现在,让我们在1 警告:

alert(x()); // 'foobar', so both 'this' variables are set

再次,让我们直列x()

// next assignment can be simplified because
// top "this" is window or the global scope
//this.bar = "bar"; =>
bar = "bar";
// at this moment both global "foo" and "bar" are set
alert(foo + bar); // => "foo" + "bar" => "foobar"

第二届警报也同样简单:

alert(x.bar); // undefined - but wasn't it used correctly?

它并不需要太多的改写。 x是一个函数,我们没有任何属性添加到它,所以x.bar是不确定的。 如果添加它,你可以看到的结果:

x.bar = "bar2";
alert(x.bar); // bar2

第三届警报演示JavaScript的OOP在行动:

alert(new x().bar); // ok, works

(旁注:它的作品只是因为你跑x()第一次,否则它吹起来,因为bar是不确定的)。

让我们把它改写这样的:

var t = new x();
alert(t.bar); // bar

现在让我们来分析构造函数。 它有两种说法:一种分配和回报。 后者被忽略,因为它返回一个字符串。 因此,我们可以把它改写这样的:

x = function(){
  this.bar = "bar";
};
var t = new x();
alert(t.bar); // bar

我希望这一切现在看起来很容易。



Answer 2:

这主要抱怨的新运营商...

该运营商创建一个新的对象,从操作数构造函数的原型继承,然后调用该函数,指定新的对象来this

如果你忘记调用构造函数时要使用的新的运营商,你会得到,而不是正常的函数调用,而this势必全局对象( window ),而不是到一个新的对象。

你的功能将被追加的全局变量时,它使用this试图初始化自己的实例。

在您的例子中,全局对象结束了两个新的变量:

window.foo
window.bar

正因为如此有些人喜欢原型继承 ,而不是伪经典方法。



Answer 3:

要回答你在你的标题提出这样的问题: this将引用全局对象。

请记住, this并不在JavaScript表现为它在如Java或C ++语言?; 它是纯粹用于上下文,并不会每一个给定函数被调用时一定指向同一类型的对象。 从MDC文件 :

有四种方法this可以通过
[...]
如果没有上述的方式被使用的,全局对象作为上下文对象,例如,当这发生在顶层任何构造的外侧通过,或当一个函数被调用,而不称为一个对象的方法,如在func(arg1, arg2)

为您解答问题的其余部分,请参阅: 当我以为我终于明白的Javascript范围...



Answer 4:

由于Shog9说,这是不一样的正常范围界定就像你在Java等见

据我所知JavaScript使用动态范围界定,像Common Lisp的/ elisp的做,而不是词法作用域像计划/ Lisp的-1一样。



文章来源: What is 'this' before an object is instantiated in js?