Object methods assigned to variables or function arguments fail when invoked

后端 未结 5 920
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-21 13:11

I\'m learning javascript right now, seems like beautiful functional language to me, it is wonderful move from PHP, I should have done this earlier. Although, I cannot figure

相关标签:
5条回答
  • 2020-12-21 13:34

    I don't know if this is an acceptable solution, but you can do:

    v1 = function(exp) { return (/[abc]/).test(exp); }
    v1('a');
    
    0 讨论(0)
  • it works with my own functions

    You are not using this inside the function. Consider this example:

    var obj = {
        foo: 42,
        bar: function() {
            alert(this.foo);
        }
    };
    var f = obj.bar;
    f(); // will alert `undefined`, not `42`
    

    It should work on methods too, since functions are just methods of parent object anyway, right?

    "Method" is just a colloquial term for a function assigned to a property on object. And functions are standalone values. There is no connection to the object a function is assigned to. How would this even be possible, since a function could be assigned to multiple objects?

    Why doesn't this work?

    What this refers to inside a function is determined at run time. So if you assign the function to a variable and call it later

    var v1 = (/[abc]/).test;
    v1('a');
    

    this inside the function will refer to window, not to the regular expression object.

    What you can do is use .bind [MDN] to explicitly bind this to a specific value:

    var a = ['a', 'b', 'c'];
    var pattern = /[abc]/;
    a.every(pattern.test.bind(pattern));
    

    Note though that since .bind returns a function, the only advantage over using a function expression is that it is a tad shorter to write.


    Is it limitation in passing built-in functions around?

    No, the problem exists for every method/function because that's how functions work. The nice thing about built-in functions though is that they often explicitly tell you when this is referring to the wrong type of object (by throwing an error).


    Learn more about this.

    0 讨论(0)
  • 2020-12-21 13:47

    Your reference to the method has lost its knowledge of what it was a method of. This isn't so much good practice as just the way JS works.

    You can do:

    var v1 = /[abc]/;
    v1.test('a');    
    

    If you must encapsulate the test method, then you could do:

    var v1 = function(str){
        return /[abc]/.test(str);
    };
    v1('a');
    
    0 讨论(0)
  • 2020-12-21 13:57

    If you store just a method, it does not carry with it a reference to your object - it just stores a reference to the .test method, but no particular object. Remember, a method is "just" a property on an object and storing a reference to a method doesn't bind it to that object, it just stores a reference to the method.

    To invoke that method on a particular object, you have to call it with that object.

    You can make your own function that calls the method on the desired object like this:

    var v1 = function(x) {
        return /[abc]/.test(x);
    }
    

    Then, when you do this:

    v1('a');
    

    It will execute the equivalent of this in your function:

    /[abc]/.test('a');
    

    But, it isn't entirely clear why you're doing that as you could also just define the regex and call .test() on it several times:

    var myRegex = /[abc]/;
    console.log(myRegex.test('a'));
    console.log(myRegex.test('b'));
    console.log(myRegex.test('z'));
    
    0 讨论(0)
  • 2020-12-21 13:57

    The test function expects this to be a regular expression. The expression /[abc]/.test gives an unbound function (it does not remember that it belongs to /[abc]/). When you invoke it like you do, this will be undefined and the function will fail.

    You can use bind to make the function remember the object it belongs to:

    var v1 = /[abc]/.test.bind(/[abc]/);
    

    or

    var v1 = RegExp.prototype.test.bind(/[abc]/);
    
    0 讨论(0)
提交回复
热议问题