Below is a ES5 shim for JS binding.I dont understand self.apply in the bound function.
I know how to use apply method, but where is self pointing to in this case ? It it supposed to be a
function, but here self looks like an object.
if ( !Function.prototype.bind ) {
Function.prototype.bind = function( obj ) {
var slice = [].slice,
args = slice.call(arguments, 1),
self = this,
nop = function () {},
bound = function () {
return self.apply( this instanceof nop ? this : ( obj || {} ), // self in this line is supposed
to // represent a function ?
args.concat( slice.call(arguments) ) );
};
nop.prototype = self.prototype;
bound.prototype = new nop();
return bound;
};
}
self is being used in the shim you have listed to accommodate the fact that this changes along with scope changes. Within the direct scope of the Function.prototype.bind function this will refer to the object on which the bind function was called.
Once you enter the scope of the nested bound function this has changed; so the author has assigned self = this within the bind function to allow the value of this at the time bind is called to remain available to the bound function via lexical scoping (closure).
Scoping within JavaScript can get pretty complicated; for a detailed explanation take a look at this article.
Everything you wanted to know about JavaScript scope.
Have in mind that in javascript almost everything is an object.
So you have it right there:
self = this
So, self is not representing anything, self is the instance.
Related
I am new to Lua, I am studying this video. At 38:56, a code is presented as below:
Sequence = {}
function Sequence:new()
local new_seq = {last_num = 0}
self.__index = self
return setmetatable(new_seq, self)
end
function Sequence:next()
print(self.last_num)
end
My understanding is that self is equivalent to Sequence, and self is set as a metatable of new_seq, and this metatable's __index is also self.
And last_num is one key of table new_seq but not one key of self, how come in the definition of next function you can write self.last_num as treating last_num is one key of self?
Moreover, before calling setmetatable, there is self.__index = self, I thought only metatable has __index as a special key, but before calling
setmetatable, Sequence is just a regular table and it is not a metatable yet, how come it has __index?
Short version:
My understanding is that self is equivalent to Sequence…
self is an implicit argument resulting from the method-style function definition. Within the function, it will refer to whatever value gets passed in as the first argument to that function.
(The rest of your questions around self arise from that same confusion.)
I thought only metatable has __index as a special key…
A metatable is just a table. __index is just a key like any other, you can define a field with that name on any table. Only when a lookup on a table fails and Lua notices that this table has an attached metatable, the metatable's field named __index has a special meaning – because that's where Lua will look for a handler.
__index containing a table is just another special case of a handler (because it's so common), __index = some_other_table is roughly equivalent to __index = function( table, key ) return some_other_table[key] end – i.e. "go look over there in some_other_table if table[key] was empty". (It may help to use the long version and print something from there if you have trouble following what happens.)
Long version, de-sugaring the code and walking through the details:
A definition function foo:bar( ... ) is the same as function foo.bar( self, ... ) (the name self is automatically chosen, roughly like this in other languages). Additionally, function foo.bar( ... ) is the same as foo.bar = function( ... ). Which means the above code is the same as…
Sequence = {}
Sequence.new = function( self )
local new_seq = { last_num = 0 }
self.__index = self
return setmetatable( new_seq, self )
end
Sequence.next = function( self )
print( self.last_num )
end
…which is equivalent to…
Sequence = {
new = function( self )
local new_seq = { last_num = 0 }
self.__index = self
return setmetatable( new_seq, self )
end,
next = function( self )
print( self.last_num )
end,
}
So, in essence, what this defines is a table that contains two functions, each taking a single parameter. The second of the two functions, next, is pretty simple: it just prints the content of the field last_num of whatever table it's passed (using the name self to refer to it).
Now, just as for definitions, there's some :-syntax sugar for calls. A call foo:bar( ... ) translates to foo.bar( foo, ... ), so when you have some_sequence and say some_sequence:next( ), what happens is a call some_sequence.next( some_sequence ) – the :-syntax for definitions introduces an extra hidden parameter and the :-syntax for calls fills in that extra parameter. In this way, the function that you're treating as a method has access to the table that you're treating as an object and everything works out nicely.
The new function is a bit more involved -- I'll rewrite it into yet another equivalent form to make it easier to read:
function Sequence.new( self )
self.__index = self
return setmetatable( { last_num = 0 }, self )
end
So for whatever table gets passed in, it assigns that table to the field __index of that same table and returns a new table with that old table set as the metatable. (Yes, this thing is confusing… don't worry, just keep reading.) To see why and how this works, here's an example:
If you say some_sequence = Sequence:new( ), you'll have the following structure:
some_sequence = { last_num = 0 } -- metatable:-> Sequence
Sequence = { new = (func...), next = (func...), __index = Sequence }
Now, when you say some_sequence:next( ), this translates to the call some_sequence.next( some_sequence ). But some_sequence doesn't have a field next! Because some_sequence has a metatable, Lua goes and looks at that – in this case, the metatable is Sequence. As a lookup (or "index") operation "failed" (it would have returned nil), Lua looks for a handler in the metatable's field __index, finds a table (Sequence again) and re-tries the lookup on that one instead (finding the next function we defined).
Which means in this case we could have equivalently written Sequence.next( some_sequence ) (but in general you don't want to – or can't – manually resolve these references). As described above, next just prints the value of the field last_num of the table it received -- in this case it got some_sequence. Again, everything works out nicely.
Some more remarks (and yet another example):
For an introductory example, the code is much more mind-bending and brittle than necessary. Here's yet another version (that's not identical and actually behaves differently, but should be easier to understand):
Sequence = { }
Sequence.__index = Sequence
function Sequence.new( )
return setmetatable( { last_num = 0 }, Sequence )
end
function Sequence:next( )
print( self.last_num )
end
Both the version that you have and this version will print 0 when you run the following:
some_sequence = Sequence:new( )
some_sequence:next( )
(I've described above what happens under the hood when you do this for your code, compare and try to figure out what happens with my version before reading on.)
This will also print 0 for both versions:
sequences = { [0] = Sequence }
for i = 1, 10 do
local current = sequences[#sequences]
sequences[#sequences+1] = current:new( )
end
local last = sequences[#sequences]
last:next( )
What happens under the hood differs significantly for both versions. This is what sequences will look like for your code:
sequences[0] = Sequence -- with __index = Sequence
sequences[1] = { last_num = 0, __index = sequences[1] } -- metatable:->Sequence
sequences[2] = { last_num = 0, __index = sequences[2] } -- metatable:->sequences[1]
sequences[3] = { last_num = 0, __index = sequences[3] } -- metatable:->sequences[2]
...
and this is what it will look like with my version:
sequences[0] = Sequence -- __index = Sequence, as set at the start
sequences[1] = { last_num = 0 } -- metatable:->Sequence
sequences[2] = { last_num = 0 } -- metatable:->Sequence
sequences[3] = { last_num = 0 } -- metatable:->Sequence
...
(If you'd instead say sequences[#sequences+1] = Sequence:new( ) in the loop above, your code would also produce this.)
With my version, the call last:next( ) fails to find next, looks at the metatable (Sequence), finds an __index field (again, Sequence) and finds next, then proceeds to call it as described above.
With your version, the call last:next( ) fails to find next, looks at the metatable (sequences[9]), finds an __index field (sequences[9]), fails to find next and therefore looks at the metatable (of sequences[9], which is sequences[8]), finds an __index field (sequences[8]), fails to find next and therefore looks at the metatable ... (until we reach sequences[1]) ... fails to find next, looks at the metatable (Sequence), finds an __index field (Sequence) and finally finds next, then proceeds with the call. (This is why I said it's quite hard to follow...)
The code that you have implements prototype-based OOP, with all the pros and cons. As you've seen, the lookup traverses the whole chain, which means that you could define a function sequences[5].next to do something else and subsequently sequences[5] through sequences[10] would find that other function. This can be really useful – no need for all the boilerplate to define a new class to change some functionality, just adjust one object and use it like a class. (This can also be annoying if you accidentally do this.)
My version implements something a bit closer to the class-based OOP seen in many other languages. (You can't accidentally override methods for more than one object at once.) What both of these (and many other approaches to OOP in Lua) have in common is that defining a field of an object with the same name as a method will hide that method and make it inaccessible. (If you define some_sequence.next, saying some_sequence:next( ) or some_sequence.next( some_sequence ) will immediately find the next you defined and Lua won't bother to look at the metatable and so on.)
I am aware that Lua classes can be created using the OO system that Luabind exposes to Lua:
http://www.rasterbar.com/products/luabind/docs.html#defining-classes-in-lua
class 'lua_testclass'
function lua_testclass:__init(name)
self.name = name
end
function lua_testclass:print()
print(self.name)
end
a = lua_testclass('example')
a:print()
However I am unable to figure out how to scope the class within another namespace so I can do the following:
a = MyScope.lua_testclass('example')
a:print()
Anyone has a idea. I do not want my classes to pollute the global namespace in Lua.
Luabind's class function will always pollute the global table. However, you can clean up after it:
function newclass(name)
oldglobal = _G[name]
class(name)
cls = _G[name]
_G[name] = oldglobal
return cls
end
Then you would use it like this:
MyScope.lua_testclass = newclass 'lua_testclass'
Analogous to local mod = require 'mod' you have to spell the name of the class twice, but you could easily build another function on top of this that could be used like setclass(MyScope, 'lua_testclass'), automatically putting the class into MyScope:
function setclass(scope, name) scope[name] = newclass(name) end
Disclaimer: All this code is entirely untested.
I did mine a little differently, but it's generally the same concept. Mine doesn't create the class, but rather just moves it. I also implemented it on the C++ side.
To implement what I did in Lua, you would write:
function moveClass(name)
oldGlobal = _G[name]
_G[name] = nil
return oldGlobal
end
To implement it in C++, you would write:
luabind::module(lua) [
luabind::def("moveClass", +[](lua_State * lua, std::string name) {
// In the case the class does not exist, this will just
// remove nil and return nil. That essentially does nothing.
luabind::object oldGlobal = luabind::globals(lua)[name];
luabind::globals(lua)[name] = luabind::nil;
return oldGlobal;
})
];
So now if you were to use that to move a class you created, you would do this:
class 'MyClass'
myTable = {}
myTable.MyClass = moveClass 'MyClass'
As an extra note, if you want the moveClass function to give an error in the case that the class you are trying to move does not exist, use luabind::type(oldGlobal) == LUA_TNIL to determine if the class existed or not.
Example:
luabind::module(lua) [
luabind::def("moveClass", +[](lua_State * lua, std::string name) {
luabind::object oldGlobal = luabind::globals(lua)[name];
if (luabind::type(oldGlobal) == LUA_TNIL) {
throw std::runtime_error("Class does not exist.");
}
luabind::globals(lua)[name] = luabind::nil;
return oldGlobal;
})
];
I'm trying to draw some stuff using wxlua.
ExampleClass = {}
function ExampleClass:New(someWxPanel)
local obj = {}
setmetatable(obj, self)
self.__index = self
self.m_panel = someWxPanel
return obj
end
function ExampleClass:OnPaint()
local dc = wx.wxPaintDC(self.m_panel)
--paint some stuff
end
local example = ExampleClass(somePanel)
somePanel:Connect(wx.wxEVT_PAINT, example.OnPaint)
I get the following error message:
wxLua: Unable to call an unknown method 'm_panels' on a 'wxPaintEvent' type.
While in any other function I define as Example:SomeFunction() self points to my Example instance and I can perfectly access its members here self is a wxPaintEvent?
How did this happen? Does the Connect somehow change self? How can I access my members now?
Appreciate any help!
When you register example.OnPaint as the event handler in somePanel:Connect(wx.wxEVT_PAINT, example.OnPaint), it always gets the event as the first parameter, but your method expects the object (self) passed as the first parameter, hence the error you get. You need to replace the registration with something like this:
somePanel:Connect(wx.wxEVT_PAINT, function(event) example:OnPaint(event) end)
Can you alias a function (not in a class) in LUA in a similar way to Ruby? In ruby you would do something like this:
alias new_name_for_method method()
def method()
new_name_for_method() # Call original method then do custom code
i = 12 # New code
end
I'm asking because I'm developing for a program that uses LUA scripting and I need to override a function that is declared in a default file.
In Lua, functions are values, treated like any other value (number, string, table, etc.) You can refer to a function value via as many variables as you like.
In your case:
local oldmethod = method
function method(...)
oldmethod(...)
i = 12 -- new code
end
keep in mind that
function method() end
is shorthand for:
method = function() end
function() end just creates a function value, which we assign to the variable method. We could turn around and store that same value in a dozen other variables, or assign a string or number to the method variable. In Lua, variables do not have type, only values do.
More illustration:
print("Hello, World")
donut = print
donut("Hello, World")
t = { foo = { bar = donut } }
t.foo.bar("Hello, World")
assert(t.foo.bar == print) -- same value
FYI, when wrapping a function, if you want its old behavior to be unaffected for now and forever, even if its signature changes, you need to be forward all arguments and return values.
For a pre-hook (new code invoked before the old), this is trivial:
local oldmethod = method
function method(...)
i = 12 -- new code
return oldmethod(...)
end
A post-hook (new code invoked after the old) is a bit more expensive; Lua supports multiple return values and we have to store them all, which requires creating a table:
local oldmethod = method
function method(...)
local return_values = { oldmethod(...) }
i = 12 -- new code
return unpack(return_values)
end
In lua, you can simply override a variable by creating a new function or variable with the same name.
function name_to_override()
print('hi')
end
If you still want to be able to call the old function:
local old_function = name_to_override
function name_to_override()
old_function()
print('hi')
end
I'm just starting to write my first FF extension using javascript modules (rather than trying an XPCOM component) but I'm fuzzy on what happens when a jsm is loaded.
Q: Does the file scope act as a closure for non-exported symbols, or are unreferenced symbols simply garbage collected?
For an example, could/should a module be written as follows?
//modules/myModule.js
var EXPORTED_SYMBOLS = [ 'foo', 'bar' ];
var data;
function foo(){
return data;
}
function bar(newData){
data = newData;
}
importing it somewhere else as:
var aNS = {};
Components.utils.import("resource://myext/myModule.js", aNS);
aNS.bar('it works?');
alert(aNS.foo()); //alert: 'it works?'
Even if a module can be written this way, is there a good reason not to?
It acts in closure manner, but only if you're referencing it somewhere. In my extension I have something like:
var EXPORTED_SYMBOLS = ['foo'];
let cacheService = Components.classes["#mozilla.org/network/cache-service;1"]
.getService(Components.interfaces.nsICacheService);
let foo = {
svc : cacheService,
dosomethingwithit : function(){this.svc.somemethod();}
}
So because it is referenced by foo.svc my cacheService is well and alive. If I wasn't referencing it anywhere it would've been garbage collected - which is to no surprise since if it's not used who cares.
But now thinking a bit more about it, I'm just wandering why I did it this way. Doesn't really makes much sense, or difference. I could've had something like:
var EXPORTED_SYMBOLS = ['foo'];
function something(){
this.svc = Components.classes["#mozilla.org/network/cache-service;1"]
.getService(Components.interfaces.nsICacheService);
}
let foo = new something();
I think I just liked the looks of the first approach more.