【问题标题】:Why is 'this' not taking on the correct scope为什么“this”没有呈现正确的范围
【发布时间】:2024-04-16 09:55:02
【问题描述】:

好的,我知道在 JavaScript 中关于this 的范围有几千个奇怪的线程(这让人怀疑该语言是否设计得很好)——但我仍然无法解释“这个”:

//works
function Cat() { 
 this.theCatName = "Mistigri"; 
 function meow() {alert(this.theCatName + " meow") }; 
 this.meow = meow }
}
var MyCat = new Cat()
MyCat.meow() 

//works
function Cat() { 
this.theCatName = "Mistigri"; 
function meow() {alert(this.theCatName + " meow") }; 
this.meow = function() { alert(this.theCatName + " meow") }
}
var MyCat = new Cat()
MyCat.meow() 

//works
function Cat() { 
this.theCatName = "Mistigri"; 
function meow() {alert(this.theCatName + " meow") }; 
Cat.prototype.meow = function() { alert(this.theCatName + " meow") }
}
var MyCat = new Cat()
MyCat.meow() 

//doesn't work
function Cat() { 
this.theCatName = "Mistigri"; 
function meow() {alert(this.theCatName + " meow") }; 
this.meow = function() { meow() } }
}
var MyCat = new Cat()
MyCat.meow() 

//doesn't work
function Cat() { 
this.theCatName = "Mistigri"; 
function meow() {alert(this.theCatName + " meow") }; 
Cat.prototype.meow = function() { meow() } }
}
var MyCat = new Cat()
MyCat.meow() 

现在我的理解是,在后两种情况下,Cat.prototype.meowthis.meow 是匿名函数,恰好调用 meow(),这是 Cat() 的内部函数 - 但 this 的上下文很清楚指函数内部的 cat - 它会发生什么?

这是一个半规范的答案: See How to access the correct this / context inside a callback? 但它只有以下内容来说明“this”的实际上下文是什么:

this(又名“上下文”)是每个函数中的一个特殊关键字,并且 它的值仅取决于函数的调用方式,而不取决于 如何/何时/何地定义它。它不受词法作用域的影响, 像其他变量一样。

【问题讨论】:

    标签: javascript scope


    【解决方案1】:

    当您调用对象的方法时,它仅在您将其作为对象的成员调用时才有效,如果您获得对该函数的引用或将其作为常规函数调用,则上下文不是对象。只是你调用函数的方式决定了上下文,上下文不是继承的,所以如果你从一个方法调用一个函数,它只是一个常规的函数调用。

    例子:

    function Dog() {
    
      function bark() {}
      this.bark = bark;
    
      this.barkThrice() {
        bark(); // function call; context = window
        this.bark(); // method call; context = the object
        var b = this.bark;
        b(); // function call; context = window
      }
    
    }
    

    要将函数作为对象的方法调用,您需要使用call method(或bindapply)来设置调用的上下文:

    function Cat() { 
      this.theCatName = "Mistigri"; 
      function meow() { alert(this.theCatName + " meow"); } 
      this.meow = function() { meow.call(this); };
    }
    var MyCat = new Cat();
    MyCat.meow();
    

    演示:http://jsfiddle.net/k6W9K/

    【讨论】:

    • 编辑:我了解如何解决它,但我不明白“this”的上下文实际发生了什么。 meow() 是 Cat() 的一个函数,被 Cat() 的另一个函数调用,这两个函数在它们的上下文中都有 this.theCatName?那么当找不到 theCatName 时,“this”试图引用什么?
    • @user3467349:函数meow不是对象的成员,它是Cat函数内部的一个函数。 Javascript 没有类作用域,其中的所有内容都是类的一部分。
    【解决方案2】:

    我希望这会有所帮助: 在函数中声明的变量在该函数之外是不可访问的。 函数内定义的变量可以被其嵌套函数访问。

    function Cat() {
    
        // public var exist on the Cat instance: accesible from outside the Cat constructor
        this.theCatName = "Mistigri";
    
        // public function exist on the Cat instance
        // has access to all variables defined in the Cat constructor (_theCateName and _meow)
        // and all variables and methods defined on 'this'
        // this reference to a Cat Instance
        this.meow = function() {
            alert(this.theCatName);
            _meow();
        }
    
        // private var only accessible within the Cat constructor.
        var _theCateName = "_Mistigri"
    
        // private function only accessible within the Cat constructor.
        function _meow() {
            // _meow is defined as closure in the Cat constructor
            // In the function _meow 'this' is a reference to the scope from where the Cat function / constructor was applied (the window object in this case)
    
            alert(this.theCatName + " meow " + _theCateName); // outputs: undefined meow _Mistigri
        };
    
    }
    var MyCat = new Cat()
    MyCat.meow()
    
    alert (MyCat.theCatName)// outouts: Mistigri
    

    【讨论】:

      最近更新 更多