有没有办法在JavaScript中修改'this'? [英] Any way to modify 'this' in JavaScript?

查看:100
本文介绍了有没有办法在JavaScript中修改'this'?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我找到了这个答案:如何修改this在javascript

但我不喜欢它。肯定有办法以某种方式修改这个

But I did not like it. Surely there must be a way to somehow modify this?

这是一个例子:

(function()
{

    var a = function(v)
    {
        v += 10;

        a = function()
        {
            console.log(this);
            this += 5; // How to "unlock" 'this'?
            console.log(this);
        }.bind(v)

        //a();
    }

    a(0);
    a();

})();

小提琴: https://jsfiddle.net/ahvonenj/mz19aku6/

如果你注释掉这个+ = 5 部分,控制台说这个 Number {[[PrimitiveValue]]:10} 。所以我没有看到为什么 Number (PrimitiveValue)类型无法增加5并打印出来的原因。我在这里缺少什么?

If you comment out the this += 5 part, the console says that this is Number {[[PrimitiveValue]]: 10}. So I do not see a reason why a Number (PrimitiveValue) type could not be increased by 5 and printed out. What am I missing here?

有没有办法突破引擎思维这个并以某种方式强行将转换为它所说的内容 - Number 在这种情况下?

Is there a way to "break out" of the engine thinking this as this and somehow forcefully convert this to what it says it is - Number in this case?

也许通过某种方式使一个接受的函数将作为参数转换并返回一个新的提供反弹的函数 bind

Maybe by somehow making a function that accepts a to-be-converted this as an argument and returns a new function which has the supplied this rebound with bind?

注意:我不打算用可能的解决方案做任何实际的事情。我只是从技术角度或其他方面感到好奇。

Note: I am not looking for doing anything practical with a possible solution. I am just curious from a technical standpoint or something.

编辑:所以名为Oriol的用户告诉我这个实际上并不是一个值为10的Number对象,而是一个Number文字。这显然意味着这个+ = 5 几乎与在这种情况下写 10 + = 5 相同。我试过像这样退房:

So a user named Oriol told me that this is not actually a Number object with a value of 10, but Instead a Number literal. This apparently means that this += 5 is almost the same as writing 10 += 5 in this case. I tried checking out out like so:

(function()
{

    var a = function(v)
    {
        v += 10;

        a = function()
        {
            console.log(this);
            var p = this + 5; // How to "unlock" 'this'?
            console.log(p);
        }.bind(v)

        //a();
    }

    a(0);
    a();

})();

所以 var p = this + 5 是现在与编写 var p = 10 + 5 基本相同,这正是我们所期望的。

So var p = this + 5 is now basically the same as writing var p = 10 + 5, which is what we expected.

推荐答案

您可以将视为函数调用附带的隐式不可变值。

You can think of this as an implicit, immutable, value accompanying a function call.

有很多方法可以设置,最常见的是调用形式的()设置这个 o f 。当然,也可以使用调用设置,应用绑定,以及其他方式。

There are a number of ways it can be set, the most common being that a call of the form o.f() sets this to o within f. Of course, this can also be set with call and apply and bind, and in other ways as well.

this 与其他函数参数不同。如果是正常参数,理论上可以更改其值。相反,它代表,一种词汇占位符,用于的值。换句话说,如果我打电话

this is not like other function parameters. If were a normal parameter, its value could in theory be changed. Instead, it represents a value, a sort of lexical placeholder for the value of this. In other words, if I call

f.call(5)

然后写

function f() { console.log(this); }

您可以将视为被词汇替换为值5.所以如果我试着写

You can think of the this as being lexically replaced by the value 5. So if I tried to write

function() { this += 5; }

你可以认为这相当于

function() { 5 += 5; }

这显然是胡说八道。我不能用其他东西替换值5。出于同样的原因,如果我说

which is obvious nonsense. I cannot replace the value 5 with something else. By the same token, if I said

o = {
  f: function() { this = o2; }
};

然后拨打 of(),函数基本上被重写为

and then call o.f(), the function is essentially rewritten as

function() { { f: ... } = o2; }

这等同于废话。我无法重新分配对象的值。

which is equal nonsense. I cannot re-assign the value of an object.

由于这个是一个值,而不是一个参数,它无法分配或更改。它不是作业的有效左侧,只有 42 。我们无法更改名为 42 的值的值。我们无法更改名为的值的值。

Since this is a value, not a parameter, it cannot be assigned to or changed. It is not a valid left-hand-side for an assignment, any more than 42 is. We cannot change the value of the value named 42. We cannot change the value of the value named this.

原因是规格。从理论上讲,人们可以想象一个JavaScript的版本,其中这个 是可变的。没有明确的理由说明为什么这是不可能的。毕竟,无论它来自哪里,在函数中它只是一个值。这会让人感到困惑,并可能导致意外行为,但没有理由说它无法正常工作。

The reason for this is that is the specification. In theory, one can imagine a version of JavaScript where this was mutable. There is no definitive reason why this should not be possible. After all, no matter where it comes from, within the function it is simply a value. It would be confusing, and could result in unexpected behavior, but there is no reason why it could not work.

不支持此主要原因的原因不在于语言的定义方式。如果你的问题是为什么语言是这样定义的,那么这就是语言历史学家要回答的问题。但是,人们可以想象这很好的理由,涉及直观的代码行为。

The primary reason this is not supported is simply that that is not how the language is defined. If your question is "why is the language defined that way", then that is something for language historians to answer. However, one can imagine good reasons for this, involving intuitive code behavior.

考虑以下代码:

o = {
  f: function() { 
    this.doSomething();
    this = o2;
    this.doSomething();
};

普通人很难理解这些代码。同样的两个 this.doSomething()调用做了两件不同的事情,因为对这个进行了干预。仅此一项是禁止更改的值的充分理由。更是如此,因为没有合理的理由需要这样做,因为我可以用简单的 o2.doSomething()替换最后两行。

It is going to be extremely hard for normal human beings to understand such code. The same two this.doSomething() calls do two different things due to the intervening change to this. This alone is a more than adequate reason to prohibit changing the value of this. All the more so since there is no logical reason for needing to do this, since I can replace the last two lines with a simple o2.doSomething().

当然,当我们谈论改变这个时,即使我们可以做到这一点,我们可以不,我们不可能意味着以某种方式改变外部价值这个指的是。我们都知道在以下情况中:

Just to be clear, of course when we talk about "changing this", even if we could do that, which we can't, we couldn't possibly mean somehow changing the outside value this refers to. We all know that in the following case:

function a(x) { x = 2; }
var y = 1;
a(y);

在<$ c内更改为 x $ c> a()纯粹是本地的,不可能影响 y 。同样的事情同样适用于这个

The change to x within a() is purely local, and can't possibly affect y. The same thing would apply equally to this of course.

关于包装基元的对象的另一个注释。我们知道我们可以写

One more note on objects wrapping primitives. We know we can write

o5 = Object(5);

获取一个包装数字5的对象。现在我可以在这个对象上定义一个方法,如

to get an object wrapping the number 5. Now I can define a method on this object, as in

o5.f = function() { console.log(this); };

并且调用 o5.f()将log

Number {[[PrimitiveValue]]: 5}

因为这个对象是一个数字,当然在这种情况下我应该可以说

So since this object "is" a number, certainly in this case I should be able to say

o5.f = function() { this++; };

但没有。 不是数字5;这是一个包装对象5.这是两个非常不同的东西。上面的函数基本上等于说

But no. this is not the number 5; it's an object wrapping 5. Those are two very different things. The function above is essentially equivalent to saying

o5.f = function() { Object(5)++; }

产生

Uncaught ReferenceError: Invalid left-hand side expression in postfix operation

现在我可以对对象进行算术运算,例如 Object(5)+ 1 ,因为JS会在添加对象之前将对象强制转换为其基础图元。但我不能再为这个对象重新分配任何其他对象了。我无法修改对象底层的原始数字。创建包装器对象后,其底层的原始值将被永久锁定。

Now I can do arithmetic on the object, such as Object(5) + 1, because JS will coerce the object to its underlying primitive before adding one. But I cannot re-assign to this object any more than any other. And I cannot modify the primitive number underlying the object. Once the wrapper object is created, the primitive value underlying it is locked in forever.

所以问题的答案是不,没有办法改变。这并不是说没有其他方法可以做其他事情来完成你想要完成的任何事情。

So the answer to your question is "no, there is no way to change this". Which is not to say there are not other ways to do other things to accomplish whatever it is you want to accomplish.

这篇关于有没有办法在JavaScript中修改'this'?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆