Js与Python函数赋值与绑定
这几天Gogo在玩Python。
作为咱学的第二门脚本语言,Gogo自然会将它与JavaScript作对比。
函数式编程
函数式编程主要有这么几个特征:
- 函数可以相互赋值
- 函数可以嵌套定义
- 函数可以作为函数的参数、返回值
实际上与面向对象十分相似:
- 对象可以相互赋值
- 类可以嵌套定义
- 对象可以作为函数的参数、返回值
Js和Py都支持函数式编程,也支持面向对象,但它们在函数赋值的地方却有些差异。
函数赋值
Js在函数赋值的地方有个小坑,先来看一段代码。
1 | var value = 5; |
为什么函数赋值以后结果会发生变化?
其实与this的变化有关。obj.fun这个方法中,this指向的是obj对象,value结果便是10。
而当obj.fun赋值给 f 时,this的值就发生了改变,指向的全局对象(浏览器上就相当于window对象)。
f() 实际上就相当于 window.f()。
想要解决这个问题也十分简单:
1 | f = obj.fun.bind(obj); |
bind 这个方法能绑定 this,上面这段代码也就指定了this指向obj,也就解决了赋值后this变化的问题。
再来看看Python,相对于Js函数赋值的诟病,Python则完全没有这样的困扰,函数赋值后self不会改变。
1 | class A: |
骤然看上去,似乎Python函数赋值机制更为完善,但其实也有它的问题。
动态添加方法
在Js里,动态给一个对象添加方法是十分简单的。
var obj = {value: 10};
obj.fun = function(){
console.log(this.value);
}
直接给属性赋值一个函数就好。
在Python中,直接赋值可能会出现问题。原因就在于Python函数中的self是不会改变的,因此必须要手动绑定self到对象。
1 | class A: |
正确的做法应该这样
1 | def bind(self, function): |
bind这个方法用于绑定一个函数到某个对象。
原理十分简单,调用obj.fun()实际调用的是call函数,call函数把self和参数传递到绑定的fun中,就实现了self的绑定。
小结
Python和JavaScript在函数赋值上的差异,似乎体现了它们不同的设计风格。
Js显得更加自由,Py则显得更加严谨。
当然这只是Gogo初窥两门语言后的想法,更多的有趣之处,得等以后再去挖掘了。