为了账号安全,请及时绑定邮箱和手机立即绑定

有时候会用一个 _this 来让 this 穿透函数定义, 但我想不是个好办法啊,还有其他方法吗?

有时候会用一个 _this 来让 this 穿透函数定义, 但我想不是个好办法啊,还有其他方法吗?

慕斯王 2023-04-28 23:19:11
一个不明白的问题. 刚开始我学的是用函数式的写法, 而且在 JS 函数嵌套函数是很容易的, 这么就搞定了.后来我接触到 JS 的 this, 理解每个函数的 this 指向自身所属对象, 接着就开始接触 OOP 的内容了.但这里有个问题, 如果我再对函数进行嵌套, this 就可能出错了.比如一个对象的方法里, 里边再定义函数用来作为参数传递..或者仅仅是 forEach 增加一层作用域:obj =   people: ['a', 'b', c]   data:    a: 'aaa'     b: 'aaa'     c: 'aaa'   say: ->     this.people.forEach (name) ->       console.log this.data[name]obj.say()在函数式编程里, 没有看到 this 这样其葩的功能, 而在有 C/Java 一类语言, 不常用嵌套函数的.就像两个东西不能很好地兼容似的... 但两个都被直接拿过来用在了脚本语言里边不知道有没有好的方案来解决?
查看完整描述

2 回答

?
慕哥9229398

TA贡献1877条经验 获得超6个赞

面向对象语言来说,举Java的例子:

class Foo {
   boolean bar() {       return this.getClass() == Foo.class;
   }   
   class InnerFoo {
       boolean baz() {           return this.getClass() == InnerFoo.class;
       }
       
       boolean baz2() {           return Foo.this.getClass() == Foo.class;
       }
   }
}

bar里面的this指向的是Foo类型的对象,baz里面的this指向的是InnerFoo类型的对象,而baz2里面的Foo.this指向的是外层的Foo类型的对象,所以需要用Foo来限定。

其实把对象本身作为参数显式的传入并不是什么bad practise,在Python中就是这样约定的:

class MyClass:    def __init__(self, name):        self.name = name        
    def greet(self, friend):
        print self.name, "says hello to", friend

所以在JS中,需要特殊的处理this绑定的问题,比如用var that = this然后引用that就是一个常用的方法。

函数编程里虽然没有this变量作为隐含参数传入,但是事实上是有更有效的工具的:闭包(closure)。事实上this变量可以算是闭包的一种情况。而在一些dynamic scoping的语言(如elisp)里面,函数的运行依赖于调用环境,所以“隐含的参数”其实更多。

我个人的看法是,面向对象里面为了方便(或者强调)封装(encapsulation),把数据和操作绑定在一起,“this”的地位才如此重要。而函数编程语言中,第一公民是函数(操作)而不是数据,所以并没有this的地位。这两者是不同的思维范式,取长补短即可。


查看完整回答
反对 回复 2023-05-02
?
蝴蝶不菲

TA贡献1810条经验 获得超4个赞

forEach这个具体的例子来看,问题倒比较容易解决,毕竟

Array.forEach(callback[, thisArg])

里可以直接将外层的this传入,这样就解决了。

从更一般的角度来看,以我愚见,定义一个var this_,虽然不太好看,但是在需要多次使用外层的this的时候,还是很方便的。
如果不需要多次使用this的话,Function.bind也可以在一定程度上解决这个问题。

想要根本上解决这个问题,也可以考虑在每个构造函数里加入类似这样的代码:

// methodNames是一个包含所有方法名称的ArraymethodNames.forEach(function(name) {    this[name] = this[name].bind(this)
}, this);

缺点是这么做会大大降低运行效率,而且也不好看。

总的来说这是Javascript的设计上的问题,只能绕过去了。

如果是用CoffeeScript的话,那么可以使用它提供的=>来定义一个保留外层this的函数:

class Tree
  constructor: (@value, @children) ->

  show: () ->
    @children.forEach (child) =>      # Note the fat arrow (=>) used here
      console.log "<Tree %s %s>", @value, child

t = new Tree "root", [1, 2, 3]
t.show()

这个功能看起来还是不错的..


查看完整回答
反对 回复 2023-05-02
  • 2 回答
  • 0 关注
  • 116 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信