Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
该';这';JavaScript中的关键字?_Javascript_Language Design - Fatal编程技术网

该';这';JavaScript中的关键字?

该';这';JavaScript中的关键字?,javascript,language-design,Javascript,Language Design,我是从语言设计的角度提出这个问题的。所以我想弄清楚 此行为的基本原理是什么 的行为在多大程度上是一个错误,或者可以改进 为了澄清为什么我对 < 感到不安,请考虑这个例子: var a = {}; a.f = function(){ return this; } var f = a.f; // f() != a.f() 注意f()所属的对象是多么容易丢失:从a中分离出来,此成为全局对象(浏览器的窗口) 现在考虑: var newA = function(){ var self = {}

我是从语言设计的角度提出这个问题的。所以我想弄清楚

  • 此行为的基本原理是什么
  • 的行为在多大程度上是一个错误,或者可以改进

  • 为了澄清为什么我对<代码> < <代码>感到不安,请考虑这个例子:

    var a = {};
    a.f = function(){ return this; }
    var f = a.f;
    // f() != a.f()
    
    注意
    f()
    所属的对象是多么容易丢失:从
    a
    中分离出来,
    成为全局对象(
    浏览器的窗口

    现在考虑:

    var newA = function(){
        var self = {};
        self.f = function(){ return self; }
        return self;
    }
    
    var a = newA();
    var f = a.f;
    // f() == a.f() !
    
    根本不需要使用
    这个
    ,我们就能够建立和维护对象上下文,而不管方法在何处或如何使用。我忍不住想,有了闭包提供的强大功能,
    这个
    变得多余,甚至有点危险

    我不是对这件事有什么仇视,也不是想开始争论;我只是想更好地理解它。我很感激“这”是有用的,但也要认识到。。。对于初学者来说,这无疑是令人困惑的,对于那些非常模糊的案例,专家们也许也是如此

    然而,在语言的其他核心方面似乎可以避免的时候(例如,Crockford和
    with
    new
    ),它仍然是语言中被大量使用且似乎备受尊重的一部分。那么,我遗漏了什么,这使得
    不可或缺?

    • 不是
    • 很多面向对象的东西
    • 就这样很好
        • 它应该被称为“自我”
        • 引用当前对象状态的任何内容
        • 通过选择“self”作为“this”的名称,并将其显式(作为第一个参数)传递给所有方法。通过这种方式,您可以很容易地区分实例方法和静态方法或函数
        对不起,我真的很喜欢Python;-)

        我认为未绑定的“this”是一个错误。否则就很方便了。未绑定的“this”可能会误解浏览器事件处理中最明显的上下文。javascript库对事件处理中的“this”应该指什么以及许多回调构造(如map、filter)也有不同的看法

        删除未绑定的“this”可能不会让事情变得更困难

        编辑:我想另一个语法示例会让我的立场更清晰

        function Foo()
        {
            //both this refer to the Foo instance
            this.blah=this.function(){this.bar;};
        
            //second this refers to baz
            this.blah=baz.function(){this.bar;};
        
            //second this refers to anonymous function itself
            this.blah=function(){this.bar;};
        }
        
        我不认为解开“这个”是个错误。一开始它有时会让人困惑,但这种情况有很好的理由。首先想到的是,由于JavaScript不是基于类的语言,函数与任何特定类都没有关联,因此没有一致的方法自动将“this”绑定到正确的对象实例。比如说,

        function Person(first, last, age) {
            this.firstName = first;
            this.lastName = last;
            this.age = age;
        }
        
        Person.prototype.getFullName = function() {
            return this.firstName + " " + this.lastName;
        };
        
        “this”需要引用Person对象,但分配给Person.prototype.getName的函数无法知道如何使用它,因此“this”需要绑定到调用它的任何对象

        这导致问题的地方是当您有嵌套函数时

        // This is a really contrived example, but I can't think of anything better
        Person.prototype.getInfo = function() {
            // get name as "Last, First"
            function getNameLastFirst() {
                // oops. "this" is the global object, *not* the Person
                return this.lastName + ", " + this.firstName;
            }
        
            // expect something like "Crumley, Matthew: Age 25",
            // but you get "undefined, undefined: Age 25"
            return getNameLastFirst() + ": Age " + this.age;
        };
        
        建议的语法会很方便,但使用apply将“this”绑定到特定对象非常容易:

        function bind(func, obj) {
            return function() {
                return func.apply(obj, arguments);
            };
        }
        
        Person.prototype.getInfo = function() {
            // get name as "Last, First"
            var getNameLastFirst = bind(function () {
                return this.lastName + ", " + this.firstName;
            }, this);
        
            return getNameLastFirst() + ": Age " + this.age;
        };
        
        或者使用闭包的更“传统”的方法:

        Person.prototype.getInfo = function() {
            var self = this;
        
            // get name as "Last, First"
            function getNameLastFirst() {
                return self.lastName + ", " + self.firstName;
            }
        
            return getNameLastFirst() + ": Age " + this.age;
        };
        
        我认为unbound'this'关键字是必要的,因为JavaScript是一种基于原型的语言。信息更灵通的人可能可以在这里填写详细信息

        事实上,这是毫无帮助的。特别是如果你想把一个对象的方法传递给一个高阶函数,事情就会变得很糟糕(下面的例子有MooTools的一些帮助):

        将不起作用,因为myObject.foo中的“this”将引用myArray而不是myObject。相反:

        myArray.each(myObject.foo.bind(myObject))
        

        这对我来说很难看。这就是为什么我通常不使用JavaScript以面向对象的方式编程,但我严重依赖闭包。

        将成语
        a.f()

        a.f.call(a);
        
        根据定义,它是使用scope
        a
        调用函数
        f

        var f = a.f;
        f(); // f.call(this);
        a.f(); // f.call(a);
        
        如果
        this
        a
        不是同一个对象,
        f()
        a.f()
        将使用不同的作用域,因此可能会有不同的行为。考虑其他语言中静态和类方法之间的区别:

        class Foo {
        public:
            static void a(Foo *scope) {
                // do something with given scope
            };
        
            void b() {
                a(this); // do something with the scope of this object
            };
        };
        
        Foo foo;
        Foo bar;
        
        foo.a(&bar) != foo.b(); // just like f() != a.f()
        foo.a(&foo) == foo.b(); // just like f.call(a) == a.f()
        

        您似乎期望它在某些OO语言中的行为,在这些语言中它总是引用方法所属的对象

        但是在JavaScript中,一个函数可以附加到多个对象,或者根本没有对象。在您的示例中,您编写了一个函数,用于一个特定对象的上下文中。。。但是没有什么能阻止我接受这个函数并将它附加到任何其他对象上。这就是语言的本质——函数是一流的,对象成员资格是可选的


        因此,这是指调用函数的上下文。现在,这是一个任意对象(通过
        .apply
        .call()
        指定)或全局对象。在该语言的未来版本中,它将引用定义函数的上下文:全局函数的全局对象,内部函数的外部
        this
        ;您可以将此视为对设计缺陷的纠正,因为在实践中,使用它引用全局对象并不是特别有用。

        是什么让您觉得“这”是一个错误?@Gamecat:您从未尝试过设计类似于javascript的语言,是吗?我仍然认为这是一个有争议的问题。该语言暗示了一个问题,cf“this(如果它是惊人的)”这不是关于js本身的问题。许多人认为这是一个挑战,即如何在js中解决“this”的缺点,或者抱怨js的设计有多么糟糕。我建议人们不要回答,除非他们从一个角度考虑
        class Foo {
        public:
            static void a(Foo *scope) {
                // do something with given scope
            };
        
            void b() {
                a(this); // do something with the scope of this object
            };
        };
        
        Foo foo;
        Foo bar;
        
        foo.a(&bar) != foo.b(); // just like f() != a.f()
        foo.a(&foo) == foo.b(); // just like f.call(a) == a.f()