What is the rationale for the behavior of the 'this' keyword in JavaScript?

前端 未结 7 797
感动是毒
感动是毒 2020-12-13 00:59

I am asking this from a language design point of view. So I am trying to find out

  1. What is the rationale for the behavior of this?
  2. To what
相关标签:
7条回答
  • 2020-12-13 02:03

    I don't think making "this" unbound was a mistake. It can sometimes be confusing at first, but there are good reasons for the way it is. The first one that comes to mind is that, since JavaScript is not a class based language, functions are not associated with any specific class, so there's not a consistent way to automatically bind "this" to the correct object instance. For example,

    function Person(first, last, age) {
        this.firstName = first;
        this.lastName = last;
        this.age = age;
    }
    
    Person.prototype.getFullName = function() {
        return this.firstName + " " + this.lastName;
    };
    

    "this" needs to refer to a Person object, but the function assigned to Person.prototype.getName doesn't have any way of knowing how it's going to be used, so "this" needs to be bound to whatever object it is called on.

    Where this causes a problem, is when you have nested functions.

    // 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;
    };
    

    The syntax artificialidiot suggested would be convenient, but it's pretty easy to bind "this" to a specific object using apply:

    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;
    };
    

    or the more "traditional" method using closures:

    Person.prototype.getInfo = function() {
        var self = this;
    
        // get name as "Last, First"
        function getNameLastFirst() {
            return self.lastName + ", " + self.firstName;
        }
    
        return getNameLastFirst() + ": Age " + this.age;
    };
    
    0 讨论(0)
提交回复
热议问题