javascript对象这个

Bas*_*sit 2 javascript reference function object this

我有一个对象,它有另一个内部对象.如何从内部对象调用父对象?

var test = {
    init: function () {
        var instance = this;
    },
    call: function() {
        this.stop(); // works
    },
    stop: function() {
        this.parseText(); // works
    },
    parseText: {
        load: function ()
        {
            this.call(); //*** dont work
            instance.call(); // work, but what if i have this instance (same name) on another object, would'nt this conflict it?
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

我正在使用一个可以正常工作的实例,但如果我或其他人在另一个对象中编写了一个实例(同名)var,它会不会冲突并覆盖这个实例呢?

T.J*_*der 9

埃里克的回答为你提供了一个如何做你想做的事情的合理例子,但并没有真正说明原因.

在JavaScript中,this完全由函数的调用方式设置(现在 ;请参阅下面的详细信息),而不是定义函数的位置,因为它在其他一些具有相同关键字的语言中(Java,C++,C#,. ..).

编码员,你决定this每次调用函数时会发生什么.主要有两种方式:通过调用通过对象属性的函数(在同一个表达式),或明确使用功能的内置callapply功能.

通过对象属性

使用对象属性:

obj.foo();    // or
obj["foo"](); // both work
Run Code Online (Sandbox Code Playgroud)

这样做有两个非常不同的东西,但它们协作设置this值:首先,通过查找foo对象的属性找到函数引用obj.然后,调用该函数.因为您将其称为检索属性值的同一整体表达式的一部分,所以JavaScript引擎将设置thisobj在调用内.

所以在你的例子中test.parseText.load(),在load调用 this中将是parseText,而不是test因为那load是被查找的对象.

请注意,setting- this-via-property-lookup仅在它们同时完成时才有效.这并不能正常工作:

var f = obj.foo;
f(); // `this` will not be `obj` within the call
Run Code Online (Sandbox Code Playgroud)

这不起作用,因为它们不是同时完成的.属性查找和函数调用是分开的.

使用callapply

第二种设置this方式更明确:所有函数都有callapply属性,它们本身就是使用您提供的信息调用函数的函数引用.在这两种情况下,第一个参数是this在调用期间使用的对象.因此,如果我们想修复上面那个不起作用的例子,我们可以这样做:

var f = obj.foo;
f.call(obj);  // `this` will be `obj` within the call
f.apply(obj); // same
Run Code Online (Sandbox Code Playgroud)

call和之间的唯一区别apply是你如何提供函数参数.使用call,您将它们作为函数的进一步离散参数提供; 用apply,你传入一个参数数组.

所以这些都做同样的事情:

// 1 - Directly via property
obj.foo("a", "b", "c");

// 2 - Using `call`
f = obj.foo;
f.call(obj, "a", "b", "c");

// 3 - Using `apply`
f = obj.foo;
f.apply(obj, ["a", "b", "c"]); // Note the `[ ... ]`, one array with three elements
Run Code Online (Sandbox Code Playgroud)

您可以看到如何call以及如何apply使用现有结构:

test.parseText.load.call(test.parseText);
Run Code Online (Sandbox Code Playgroud)

这要求test.parseText.load,使得this= test.parseText通话中.

Eric在他的回答中所做的是使用一个闭包来让你更容易调用你期望parseTextthis值.

进一步阅读(披露:来自我的博客):


我说:

在JavaScript中,this完全由函数的调用方式设置 (目前 ...

我说"现在"的原因是,在ES6中,JavaScript正在获得"箭头函数",与其他函数不同,this箭头函数的值是根据它们的创建位置设置的,而不是它们的调用方式:它们得到this从您创建它们的上下文中.

假设您在对象方法中编写代码,并希望使用该对象的另一种方法,我不知道,从数组输出信息(是的,这是设计的).在ES5中,您可能会这样做:

this.output("Entries:");
theArray.forEach(function(entry, index) {
    this.output(index + ": " + entry);
}, this);
// ^------- tells `forEach` what to use as `this` during the callback
Run Code Online (Sandbox Code Playgroud)

如果你没有参与论证,那你就有一个错误:

this.output("Entries:");
theArray.forEach(function(entry, index) {
    this.output(index + ": " + entry); // <== Bug, `this` is either
                                       // `undefined` (strict) or
                                       // the global object (loose)
});
Run Code Online (Sandbox Code Playgroud)

但是由于箭头函数继承this自它们的创建位置而不是基于它们的调用方式来获取它,因此箭头函数版本不需要第二个参数:

this.output("Entries:");
theArray.forEach((entry, index) => {
  this.output(index + ": " + entry);
});
Run Code Online (Sandbox Code Playgroud)


Eri*_*ric 7

如果你担心的只是test改变,那就这样做:

var test = (function() {
    var object = {}
    object.call = function() {
        this.stop(); // works
    };
    object.stop = function() {
        this.parseText(); // apparently works, even though parseText is not a function
    };
    object.parseText = {
        load: function() {
            object.call(); // works
        }
    };
    return object;
})();
Run Code Online (Sandbox Code Playgroud)


Rob*_*b W 5

如果您不知道名称test,可以使用自调用匿名函数来创建包装器,并参考如下所示的对象.

请注意,test它不是对函数的引用,而是对匿名函数的返回值.因为对象名称(obj)包含在函数内部,所以无法从外部读取或修改它

下面的解决方案很整洁,不会污染范围test,并且像魅力一样工作.如前所述,test指的是同一个对象obj.但是,无法obj从外部操纵变量,因此函数内部的代码会中断.

var test = (function(){ //Self-executing function
    var obj = {
        call: function() {
            this.stop(); // works
        },
        stop: function() {
            this.parseText(); // works
        },
        parseText: {
            load: function ()
            {
                obj.call();  // obj refers to the main object
            }
        }
    };
    return obj; //Return the object, which is assigned to `test`.
})(); //Invoke function
Run Code Online (Sandbox Code Playgroud)

更新

在不包装对象的情况下self,不可能可靠地引用this,或对对象内的对象的任何引用.

您当前的解决方案不起作用,请参阅以下代码中的注释:

var obj = {
   init: function(){
      var instance = this; //`instance` is declared using `var` inside a function
   },                       // This variable cannot read from "the outside"
   parseText: {
      load: function(){
          instance.call(); //Does NOT work! instance is not defined
      }
   }
}
Run Code Online (Sandbox Code Playgroud)