我刚刚在JavaScript中遇到了一个有趣的情况。我有一个类,它的方法使用对象文字表示法定义了几个对象。在这些对象中,使用了this指针。从程序的行为中,我推断this指针指向调用方法的类,而不是由文字创建的对象。

这似乎是随意的,尽管这是我所期望的工作方式。这是已定义的行为吗?它跨浏览器安全吗?是否有任何潜在的原因,为什么它会超出“规格说明”(例如,这是一些更广泛的设计决策/哲学的结果)?简化后的代码示例:

// inside class definition, itself an object literal, we have this function:
onRender: function() {

    this.menuItems = this.menuItems.concat([
        {
            text: 'Group by Module',
            rptletdiv: this
        },
        {
            text: 'Group by Status',
            rptletdiv: this
        }]);
    // etc
}

当前回答

这在JS中:

有三种不同意义的函数类型。最好通过例子来解释:

构造函数

//在构造函数中this指向新创建的对象 //每个函数都可以是JavaScript的构造函数。 函数的狗(颜色){ 这一点。颜色=颜色; } //通过在函数调用前放置new来调用构造函数 const myDog = new Dog('red'); // logs狗有红色 console.log('狗有颜色' + myDog.color);

正常的函数或方法

// Browswer example: console.log(this === window) // true function myFn(){ console.log(this === window) } myFn(); // logs true // The value of this depends on the context object. // In this case the context from where the function is called is global. // For the global context in the browser the context object is window. const myObj = {fn: myFn} myObj.fn() // logs false // In this case the context from where the function is called is myObj. // Therefore, false is logged. myObj.fn2 = function myFn(){ console.log(this === myObj) } myObj.fn2() // logs true // In this case the context from where the function is called is myObj. // Therefore, true is logged.

事件监听器

在事件处理程序的函数中,this将引用检测到事件的DOM元素。请看这个问题:在事件处理程序中使用这个

其他回答

这是已定义的行为吗?它是 跨浏览器的安全吗?

是的。是的。

这背后有什么原因吗 事情就是这样……

这句话的意思很容易推导:

如果在构造函数中使用this,并且函数是用new关键字调用的,则this引用将创建的对象。即使在公共方法中,这也将继续表示对象。 如果在其他任何地方使用它,包括嵌套的受保护函数,它引用全局作用域(在浏览器的情况下是窗口对象)。

第二种情况显然是一个设计缺陷,但是通过使用闭包可以很容易地解决它。

我找到了一个关于ECMAScript的很好的教程

这个值是一个与执行相关的特殊对象 上下文。因此,它可以被命名为上下文对象(即一个对象) 对象,在其中上下文中激活执行上下文)。

任何对象都可以用作上下文的这个值。

此值是执行上下文的属性,但不是 属性。

这个特性非常重要,因为与变量相反,这个值从不参与标识符解析过程。也就是说,当在代码中访问this时,它的值直接从执行上下文中获取,而不需要任何作用域链查找。this的值在进入上下文时只确定一次。

在全局上下文中,this值是全局对象本身(这意味着,这里的this值等于变量对象)。

对于函数上下文,这个值在每个单独的函数调用中都可能是不同的

参考Javascript-the-core和第3-this章

在这种情况下,内部的this被绑定到全局对象,而不是外部函数的this变量。 这是语言的设计方式。

请参阅Douglas Crockford所著的“JavaScript: The Good Parts”。

这在JS中:

有三种不同意义的函数类型。最好通过例子来解释:

构造函数

//在构造函数中this指向新创建的对象 //每个函数都可以是JavaScript的构造函数。 函数的狗(颜色){ 这一点。颜色=颜色; } //通过在函数调用前放置new来调用构造函数 const myDog = new Dog('red'); // logs狗有红色 console.log('狗有颜色' + myDog.color);

正常的函数或方法

// Browswer example: console.log(this === window) // true function myFn(){ console.log(this === window) } myFn(); // logs true // The value of this depends on the context object. // In this case the context from where the function is called is global. // For the global context in the browser the context object is window. const myObj = {fn: myFn} myObj.fn() // logs false // In this case the context from where the function is called is myObj. // Therefore, false is logged. myObj.fn2 = function myFn(){ console.log(this === myObj) } myObj.fn2() // logs true // In this case the context from where the function is called is myObj. // Therefore, true is logged.

事件监听器

在事件处理程序的函数中,this将引用检测到事件的DOM元素。请看这个问题:在事件处理程序中使用这个

从我的另一篇文章中摘录,这里有比你想知道的更多的东西。

在我开始之前,这里有关于Javascript最重要的事情要记住,当它没有意义的时候可以重复一遍。Javascript没有类(ES6的类是语法糖)。如果某个东西看起来像一个类,这是一个聪明的技巧。Javascript有对象和函数。(这不是100%准确,函数只是对象,但有时将它们视为独立的事物会有所帮助)

this变量被附加到函数上。无论何时调用函数,它都会被赋予一个特定的值,这取决于调用函数的方式。这通常称为调用模式。

在javascript中有四种调用函数的方法。可以作为方法、函数、构造函数和apply调用该函数。

作为方法

方法是附加到对象上的函数

var foo = {};
foo.someMethod = function(){
    alert(this);
}

当作为方法调用时,它将被绑定到函数/方法所属的对象。在本例中,this将被绑定到foo。

作为功能

如果你有一个独立的函数,这个变量将被绑定到“全局”对象,几乎总是浏览器上下文中的窗口对象。

 var foo = function(){
    alert(this);
 }
 foo();
 

这可能是让你抓狂的原因,但不要难过。许多人认为这是一个糟糕的设计决策。由于回调是作为函数而不是作为方法调用的,这就是为什么您会看到不一致的行为。

很多人通过这样的方式来解决这个问题

var foo = {};
foo.someMethod = function (){
    var that=this;
    function bar(){
        alert(that);
    }
}

你定义一个变量,它指向这个。闭包(一个自己的主题)保留了这一点,所以如果你将bar作为一个回调调用,它仍然有一个引用。

注意:在严格使用模式下,如果用作函数,则不绑定到全局。(没有定义)。

作为构造函数

还可以将函数作为构造函数调用。根据您正在使用的命名约定(TestObject),这也可能是您正在做的事情,也可能是使您出错的事情。

使用new关键字作为构造函数调用函数。

function Foo(){
    this.confusing = 'hell yeah';
}
var myObject = new Foo();

当作为构造函数调用时,将创建一个新的Object,并且this将绑定到该对象。如果你有内部函数,它们被用作回调,你会把它们作为函数调用,这将被绑定到全局对象。使用var that =这个技巧/模式。

有些人认为构造函数/new关键字对Java/传统OOP程序员来说是一种骨头,用来创建类似于类的东西。

使用Apply方法

最后,每个函数都有一个名为“apply”的方法(是的,函数在Javascript中是对象)。Apply允许您确定this的值,还允许您传入一个参数数组。这里有一个没用的例子。

function foo(a,b){
    alert(a);
    alert(b);
    alert(this);
}
var args = ['ah','be'];
foo.apply('omg',args);