【问题标题】:The meaning of `this` in JS template method patternJS模板方法模式中`this`的含义
【发布时间】:2013-12-11 06:25:52
【问题描述】:

为什么标记的行找不到protectedACMember

var Module = (function (ns) {

    function AbstractClass() {
        this.protectedACMember = "abstract";

        this.abstractPublicACMethod = function (input) {
            this.methodToImplement();                   
        }
    }

    ConcreteClass.prototype = new AbstractClass();
    function ConcreteClass(){
        var privateCCMember = "private CC";

        var privateCCMethod = function(){
            alert(this.protectedACMember); // cant find protectedACMember
        }

        this.methodToImplement = function(){ 
            privateCCMethod();
            console.log('Implemented method '); 
        }

    }

    ns.ConcreteClass = ConcreteClass;   

    return ns;

})(Module || {});

//somewhere later
var cc = new Module.ConcreteClass();
cc.abstractPublicACMethod();

有模拟私有、受保护和公共成员的好模式吗?静态/非静态也是?

【问题讨论】:

标签: javascript module-pattern template-method-pattern


【解决方案1】:

你应该像这样改变那部分代码:

    var self = this;
    var privateCCMethod = function(){
        alert(self.protectedACMember); // this -> self
    }

这样你就可以在闭包中获得引用。

原因是,“this”是一个保留字,它的值是由解释器设置的。您的 privateCCMethod 是一个匿名函数,而不是对象属性,因此如果您仅通过 privateCCMethod() 语法调用它,这将为空。 如果您希望“this”绑定到特定的东西,您可以随时使用 .call 语法,如下所示:

privateCCMethod.call(this)

【讨论】:

  • 如果我写了 function privateCCMethod() {...} 会怎样 - 那么它会是对象的属性吗?
  • 没有。在您的示例代码中,“methodToImplement”是属性。这是一种方法。另一种是像 ConcereteClass.prototype.privateCCMethod = function() {...} 一样定义它。
【解决方案2】:

确保this 表示您想要的意思的另一种方法是使用bind。绑定允许您确保使用特定值this 调用函数。

大多数较新的浏览器都支持它(甚至是 IE9!),对于那些不支持的浏览器有一个解决方法。

Bind - MDN Documentation

【讨论】:

  • 看起来像function.call
【解决方案3】:

找不到protectedACMember,因为当你输入函数privateCCMethod时,this关键字的含义发生了变化。一种常见的做法是存储外部 this 以供在函数内部使用:

function ConcreteClass(){
    var privateCCMember = "private CC";

    // store the outer this
    var that = this;
    var privateCCMethod = function(){
        alert(that.protectedACMember);
    }
    ...

您的其余问题已相当丰富,可能应该作为单独的问题发布。

【讨论】:

  • this 总是最近的封闭函数?如果我跳过this 并简单地写alert(protectedACMember) 怎么办?
  • @Queequeg 它将寻找一个名为 protectedACMember 的作用域变量并且找不到任何东西。 protectedACMember 是对象的属性。
  • 设置that 变量比使用func.call(this,...) 更好?
  • @Queequeg 是的;为protectedACMember 提供适当的上下文是privateCCMethod 的责任,而不是函数的使用者。
  • 我的意思是methodToImplement里面的电话
猜你喜欢
  • 2020-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-19
相关资源
最近更新 更多