I'm wondering if there a way to pass a value which I receive after constructor and put in in constructor options. The problem is that I also have a value from constructor which I need to pass, so it has dependencies from both sides.
class Test
constructor: (#opt={}) ->
#opt.width = obj.width
#opt.color = "#f45
# obj.width is undefined
obj = new Obj
width: 200
color: #opt.color
Or my real example.
class Button extends Layer
constructor: (#opt={}) ->
super _.defaults #opt,
width: #btnText.width
type: "default"
# btnText.width is undefined
#btnText = new Text
width: 200
type: #opt.type
How can I solve this problem and get rid of undefined values? Might be I can use some sort of await and promise? Don't know :-)
Thank you in advance!
Related
I have this fiddle
let m = new Mine();
this.setState(m, () => {
console.log('1:', m instanceof Mine, m.x, m.meth);
// => 1: true 123 function meth() {}
console.log('2:', this.state instanceof Mine, this.state.x, this.state.meth);
// => 2: false 123 undefined
});
As you can see I create an instance of the Mine class and then set state in a react component with that instance.
I would expect this.state to contain exactly that instance but while the instance properties that are set in the constructor are available I can't access any of the class methods on that instance.
The test in the fiddle shows that this.state is not an instance of the class Mine.
Does anybody understand what is going on or is this unintended behavior?
After more investigation I found out the reason why that happens.
The function _processPendingState from react uses Object.assign to set the new state, so since the target object is a new object (different than what is passed to setState) the new state loses the quality of being an instance of the "Mine" class.
And because Object.assign only copies own enumerable properties from the sources to the target the new state also won't have the class methods.
If in the fiddle we replace the line...
let m = new Mine();
with...
let m = {x: 123};
Object.defineProperty(m, 'meth', {
enumerable: false,
get() { return function() {}; }
});
we still don't have the "meth" property on the resulting state. Even if "m" owns the "meth" property it is not enumerable.
The best solution is to surface the method as an arrow function:
class Blah {
constructor() {
// no definition here for surfacedMethod!
}
surfacedMethod = () => {
// do something here
}
}
Then you can set instances of this class in setState and use their methods as if they were attributes set on the instance.
// other component innards
this.setState(state => ({blah: new Blah()}))
// later
this.state.blah.surfacedMethod(); // this will now work
In such case use replaceState, it should work.
I have a "class" in coffee script whose instance variables I want to initialize with instance methods that return a value via a callback, but it doesn't work as I had hoped:
EventEmitter = require('events').EventEmitter
class MyClass extends EventEmitter
constructor: ->
#datamember: setDatamember()
setDatamember: ->
someFunction (response) ->
#datamember = response
#emit 'init'
getDatamember: ->
return #datamember
----
myObj = new MyClass
myObj.on 'init', ->
console.log myObj.getDatamember
The result I get suggests that "this" in setDatamember is referring to something different from what "this" refers to in the object instance. If I explicitly call myObj.setDatamember, I get the expected result, but is there any way to call on a set method -- specifically one that sets the data member via a callback -- in the constructor? I've looked through the docs, as well as various other sources of coffeescript info (e.g. this one), and I haven't found anything that touches upon this.
Try using a fat arrow for the anonymous function:
setDatamember: ->
someFunction (response) =>
#datamember = response
#emit 'init'
Also, you'll need to call the correct function in the constructor:
constructor: ->
#setDatamember()
In general, avoid fat arrows on methods - the way Coffee-Script implements this does some bad things to memory usage. Also, it will rarely be necessary.
However, anonymous functions that refer to this will almost always need fat arrows. this is not held in closure like normal variables, and will only be set by binding (Function.prototype.bind) or by calling it as an object method (obj.myMethod() will set this to obj in myMethod).
Try using fat arrows on everything except the constructor:
class MyClass
constructor: ->
#setDatamember()
setDatamember: =>
someFunction (response) =>
#datamember = response
getDatamember: =>
return #datamember
However, you also look to have someFunction in there as an asynchronous function, so you'll never be able to just do
mc = new MyClass
console.log mc.datamember
Because that doesn't wait for someFunction to return before accessing mc.datamember.
I am using director class for scene transitions and i need to use the variable in a class in another class. So how can i call it?
local a= require "welcome"
variableName is text display object in welcome class
print(a.variableName.text)
However i get nil.
Could you help me out? Thanks
Make the variable a property of the returned table:
local Class = {}
function Class.new()
local class = {}
class.variableName = display.newText("Hello mom!", 100, 100, "Helvetica", 18)
return class
end
return Class
Then you can reference it:
local a = require ("class").new()
print(a.variableName.text)
OR
If you want to pass variables between the screens in Rauber's Director Class, you can:
local parameters = {p1="some text", p2="some more text"}
director:changeScene(parameters, "sceneName")
In your screen, make the new function accept the parameters:
function new(parameters)
print(parameters.p1, parameters.p2) --> some text some more text
end
OR
Put _G in front of your variable
_G.myGlobalVar = "some awesome stuff"
Then you can reference it in another class
print(_G.myGlobalVar) --> some awesome stuff
I'm trying to subclass the native JS Error object in CoffeeScript to get specialized error types, but i found that the instanceof does not work correctly if i don't define a constructor in the subclasses:
class SimpleError extends Error
class EmptyConstructorError extends Error
constructor: ->
class SuperConstructorError extends Error
constructor: ->
super
new SimpleError instanceof SimpleError # -> false
new EmptyConstructorError instanceof EmptyConstructorError # -> true
new SuperConstructorError instanceof SuperConstructorError # -> true
The problem seems to be caused by how the generated JS constructor functions are defined. When i don't define a constructor in CoffeeScript:
SimpleError = (function(_super) {
__extends(SimpleError, _super);
function SimpleError() {
return SimpleError.__super__.constructor.apply(this, arguments);
}
return SimpleError;
})(Error);
And when i do define a constructor in CoffeeScript:
SuperConstructorError = (function(_super) {
__extends(SuperConstructorError, _super);
function SuperConstructorError() {
SuperConstructorError.__super__.constructor.apply(this, arguments);
}
return SuperConstructorError;
})(Error);
As you can see, the difference is a simple return in the first case. I don't understand why this makes any difference in the instanceof behavior though, as the super constructor is just being applied to the this object (i.e. the super constructor is not being called with new), but then again i don't understand a whole lot of how JS constructors work =P
And the weird thing is that this behavior seems to only happen when subclassing native JS objects. If i subclass CoffeeScript classes everything works as expected.
Any idea of why this might be happening and how could i avoid writing dummy constructors just for the instanceof operator to work correctly?
Thanks!
Update
So the user matyr answered with a link to the commit where this behavior was introduced, but it doesn't quite explain what is happening here, so i'll try to explain that a little bit in case anyone else wonders why this works this way.
The main problem is this inherited nasty "feature" from JavaScript which let us define a constructor function that returns an object other than the one being constructed:
function Foo() {
return {'LOL': 'You fool!'};
}
new Foo() instanceof Foo // -> false
And there is also the fact that some native constructors, like Error, Array, String and whatnot don't need to be called with new: they will just return a new object of the corresponding type if you happen to forget it.
In the end, add these two ugly things together and the result is that you should remember to write class MyError extends Error then constructor: -> super instead of the more intuitive class MyError extends Error if you want the instanceof operator to work properly with MyError. That's because CoffeeScript's implicit constructor will just return whatever the parent constructor returns, and in this case will do return Error.apply(this, arguments) which will just return a shinny new error object instead of the object you passed as the this argument. Yay!
Update 2 (Feb 25 2013)
This problem was fixed in CoffeeScript 1.5.0! =D
Now extending native objects works as expected:
class MyError extends Error
new MyError instanceof MyError # -> true :)
Update 3 (Mar 04 2013)
Aaand it's gone on 1.6.0 =P
For better or worse, the return was added on 1.3.1 to fix #1966 (and #2111).
I'm trying to build a way to do PHPUnit-style test case classes in CoffeeScript. I got very close to achieving my goal with these two classes:
QUnitTestCase.coffee:
class QUnitTestCase
constructor: (name) ->
module name
#setUp()
#runAllTests()
setUp: ->
return null
runAllTests: ->
for funcName, func of #
if funcName.substr(0, 4) is 'test' and typeof func is 'function'
testName = funcName.substr(4).charAt(0).toLowerCase() + funcName.substr(5)
#setUp()
test testName, func()
return null
CircleTest.coffee:
class CircleTest extends QUnitTestCase
constructor: ->
super "Circle"
setUp: ->
#mockCanvas = mock(Canvas)
#testObj = new Circle(#mockCanvas)
$('canvas').css display: 'none'
testDrawReturnsNull: =>
returned = #testObj.draw()
strictEqual null, returned, 'returns null'
However, QUnit blows up with this error: "Uncaught TypeError: Cannot read property 'assertions' of undefined (qunit.js line 666)".
Looking at QUnit, I believe somehow the Test object inside QUnit becomes mis-scoped when the function that defines the assertions is bound to the object. If I move the call to "test()" out to the child class, like this...
testDrawReturnsNull: =>
test "drawReturnsNull", =>
returned = #testObj.draw()
strictEqual null, returned, 'returns null'
... then QUnit runs fine without any errors, but this creates a kind of duplication that I don't really feel comfortable with. Perhaps someone who understands QUnit better can point me in the right direction.
Thanks.
You wrote
test testName, func()
instead of
test testName, func
That would seem to be a problem. You want to pass the function to test rather than running it first and passing the returned value.