What does this conf do? - actionscript-3

So I was looking at a tutorial online and came across this:
function generateRobot(conf:Object = null):Robot {
var conf:Object = conf || {};
var defaults:Object = {
laserColor:red,
personality: "evil"
}
for (var key:String in defaults){
conf[key] = conf[key] || defaults[key];
}
Can someone help explain what line 2 and line 8 mean? Thanks for helping a new coder!

I have added some comments and renamed the param to make it clearer:
//param is a parameter of the type object with a default value of null that is passed
//into the function, if nothing is passed in it will be null
function generateRobot(param:Object = null):Robot {
//declare a local variable called conf and populate
//it with the parameter if it exists, otherwise create a new object {}
var conf:Object = param || {};
//create a default settings object
var defaults:Object = {
laserColor:red,
personality: "evil"
}
//loop through the default settings
for (var key:String in defaults){
//conf setting becomes param if exists otherwise use the defaults value
conf[key] = conf[key] || defaults[key];
}

The questions seems specific to the || construct in the variable assignment. As #Thilo mentioned, it is simply a way to specify a default, should the field be missing in the parameter.
For example:
function read_file(file, delete_after) {
delete_after = delete_after || "False";
//rest of code
}
would be such that, if variable delete_after is not passed when function read_file is called, then it will assume value "False", or anything after the || sign.
Some prefer an explicit check against undefined.
Other pointers to look at:
Set a default parameter value for a JavaScript function
http://www.codereadability.com/javascript-default-parameters-with-or-operator/

Related

How can I keep an array filled outside of a function?

This question is part of finding a solution to a larger problem. However, I am wondering if there is a way to use a function to fill an Array. Based on the test code below, it seems arrays automatically empty after the function. I am looking to have a function that fills the array repeatedly, and another one that triggers to paste the resulting array.Note the paintArray=[] defined outside of the functions.
The console logs '1' for fillArray() but when I run logArray() right after it logs [].
const paintArray = []
function logArray(){
console.log(paintArray)
}
function fillArray(){
paintArray.push(1)
console.log(paintArray)
}
You can use Properties Service this way:
var scriptProp = PropertiesService.getScriptProperties();
function logArray(){
Logger.log(scriptProp.getProperty("paintArray"))
}
function fillArray(){
var obj = scriptProp.getProperty("paintArray")
if(obj){ //check if paintArray Object exists
var arr = JSON.parse(obj); //parse the value to array
arr.push(1); //push value 1
scriptProp.setProperty("paintArray", JSON.stringify(arr)) //set new value of arr to properties
}else{
scriptProp.setProperty("paintArray", "[1]"); //set initial value if paintArray object is undefined
}
}
First run:
Second run:
Third run:
Save and Retrieve Array from Properties Service
function saveArray(a) {
PropertiesService.getScriptProperties().setProperty("myarray",JSON.stringify(a));
}
function getArray() {
return JSON.parse(PropertiesService.getScriptProperties().getProperty("myarray"));
}

ActionSctipt 3.0 Error:

I'm having real trouble trying to access the symbol dynamically, I have 9 buttons that all call this method, and they pass in their location (tl, t, tr, etc.) I've tried this method before on another program and it works without a problem, but in this program it fails.
I am attempting to access a symbol call s_tl (example location), but all I'm getting is undefined (see results).
function turn(btn : String):Function {
return function(e:MouseEvent) {
var players_turn : int;
var chosen : String = "s_" + btn;
trace(this);
trace(this[chosen]);
trace(chosen);
trace(this[chosen]);
// if crosses turn 0 else 1
if (s_c.currentFrame == 1) {
players_turn = 0;
} else {
players_turn = 1;
}
// check who's turn it is if it's been pressed before
if (players_turn == 0 && this[chosen].visible == false) {
this[chosen].gotoAndStop(1);
this[chosen].visible = true;
} else {
this[chosen].gotoAndStop(2);
this[chosen].visible = true;
}
};
}
Results:
[object global]
undefined
s_br
undefined
TypeError: Error #1010: A term is undefined and has no properties.
at MethodInfo-6()
Your problem is the bad code style. You define unnamed unbind function inside function turn() and that's where the root of your problem is. Unbind function exist, as your trace shows, in global addressing context and, unlike function turn(), is not bind to any specific display object. Your buttons probably exist on the same addressing context with turn(). Argument btn is available inside unnamed function because ECMA standard instructs so (if function A creates function B then local variables, including arguments, of A are available as local variables in B), but it is a very very very bad practice that makes code messy and induce headaches.
Please explain what you tried to achieve with that code so we could untangle it and rewrite in not-so-twisted way.
Okey, I basically figured you're doing Tic Tac Toe. Now, guideline. A cell must contain 3 frames: 1st frame for the button graphics, 2nd and 3rd for X and O. Name them your way: s_1, s_2, etc.
for (var i:int = 1; i < 10; i++)
{
var aCell:MovieClip = getChildByName("s_" + i) as MovieClip;
aCell.addEventListener(MouseEvent.CLICK, onTic);
}
function onTic(e:MouseEvent):void
{
var playersTurn:int = s_c.currentFrame;
var aCell:MovieClip = e.currentTarget as MovieClip;
trace(aCell.name);
// Now, the magic.
aCell.gotoAndStop(playersTurn + 1);
aCell.removeEventListener(MouseEvent.CLICK, onTic);
}

AngularJS dynamic scope variables

I have a scope variable jsonData as below:
$scope.jsonData={id:'1234',abcd:{array:[{a:'data',b:'bdata',c:'cdata'},{a2:'a2data',b2:'b2data',c2:'c2data'}]},efg:{test:'testdata'}}
in my HTML I have a function calladd('jsonData.abcd.array') with a string
in my js file I want to add an JSON object to arrayinside the abcd JSON object
$scope.add(data) {
$scope[data].push({a3:'a3data',b3:'b3data',c3:'c3data'});
}
but I am unable to push data into array.
If you wanted to get ID, you can do
var id = $scope.jsonData.id;
//id = "1234"
You can use the same logic to add or get values
Calling myobject['prop1.prop2.whatever'] just doesn't work.
What you need is a recursive parser like :
$scope.add = function(data, scope){
scope = (typeof scope === "undefined") ? $scope : scope;
var datas = data.split('.');
if(datas.length == 1){
scope[datas[0]].push({
a3: 'a3data',
b3: 'b3data',
c3: 'c3data'
});
}else{
var first = datas.splice(0,1);
$scope.add(datas.join('.'), scope[first]);
}
};
And the fiddle

ParseJSON with functions to javascript object

I have a problem that seems complicated that I don't know how to solve.
My single page application uses knockoutJS and I want to cache my view model every time one of my input values change on my view.
Where the problem lies is the complexity of my view model. To use local storage I need to stringify my object but it has recursive values. I have some logic to handle this and stringify my object. But when I try to parse the JSON string back to an object, I lose my functions.
function cacheForm(agency) {
//var serialized = stringifyOnce(agency);
//var serialized = amplify.store("Agency", agency);#
//var obj = new Object();
//obj.test = "test";
value = agency;
var cache = [];
parsed = JSON.stringify(value, function (key, value) {
if (typeof value === 'object' && value !== null) {
if (cache.indexOf(value) !== -1) {
// Circular reference found, discard key
return;
}
// Store value in our collection
cache.push(value);
}
return value;
});
//var jsonString = JSON.stringify(cache);
//cache = null; // Enable garbage collection
var parsedRecursive = "{" + '"data"' + ":" + parsed + "," + '"expires"' + ":" + null + "}"; // Build the string based on how amplify likes it
var obj = eval('(' + parsed + ')')
var obj = jQuery.parseJSON(parsedRecursive);
//// Put the object into storage
//localStorage.setItem('Agency', parsedRecursive);
myData = JSON.parse(parsedRecursive, function (key, value) {
var type;
if (value && typeof value === 'object') {
type = value.type;
if (typeof type === 'string' && typeof window[type] === 'function') {
return new (window[type])(value);
}
}
return value;
});
//// Retrieve the object from storage
// var retrievedObject = localStorage.getItem('Agency');
// var obj = jQuery.parseJSON(parsedRecursive);
//var agency2 = mapping.fromJS(obj);
//agency;
//amplify.store("Agency", agency);
//amplify.store("Obj", obj);
//var store = amplify.store(); // Look at all items by not providing a key
}
});
I tried using eval but this returned an object without my data. To help you understand this is what my view model looks like, which is the agency parameter of cachForm.
Also I tried using amplify but because of my view model structure I run into the same issue.
I have also attached some screenshots to show what happens with my viewmodel in the code.
It is not a good idea to cache the whole viewModel. A viewModel contains observables, computeds and functions or events handlers.
You have better to cache the view model data, only the raw data.
On serialization :
So just serialize the view data (use ko.mapping.toJSON):
var json = ko.mapping.toJSON(viewModel);
In order to rebuild a proper view model it is better to have a initialisation function.
This is your view model constructor e.i. a function that adds the event handlers, functions and computed.
var initializer = your_constructor;
You also need to determine a cache key e.g. the page path.
var cacheItem = {data : json, constructor : initializer};
cache[key] = cacheItem;
On deserialization :
Get the cache item :
var cacheItem = cache[key];
var viewModel = JSON.parse(cacheItem.data);
Now viewModel contains the raw data.
viewModel = ko.mapping.fromJS(viewModel);
The properties were converted into observables.
If there is a constructor call it.
if(cacheItem.constructor)
cacheItem.constructor.call(viewModel);
Then your view model is as you stored it.
I hope it helps.
This is the answer I have posted in another post. They are both related.
JSON.parse returns children objects with null value, children values not being parsed

flash get function's argument name

I want to get all arguments names of a function inside the function
example:
function fct(var1:string,var2:string){
var names:Array=...
trace(names);
}
must trace : var1,var2
Thanks!
Simply put, this is not possible. The closest you can get is the argument number and value. See below:
function fct( ... args ):void {
for ( var v:Object in args ) {
trace( v + ": " + args[v] );
}
}
var str1:String = "this is a test";
var str2:String = "this is another test";
fct( str1, str2 );
//output
//0: this is a test
//1: this is another test
For future reference, you can use ... + a variable name to allow for as many arguments as you need. Regardless, you should just need to access args[ INDEX ] rather than the actual variable name, which you wouldn't be able to access anyway because there would be no way to apply scope (such as variableName[ "propertyName" ])
It is impossible like native method, but you can use metadata tag to set arguments names. I create simple example. But i don't understand how it can help you in real projects:
[Arguments(param1="arg1",param2="arg2")]
public function test(arg1:Number, arg2:Number):void {
var desc_xml:XML = describeType(Object(this).constructor);
var metas_xml:XMLList = desc_xml.factory.method.(#name == "test");
var args_xml:XMLList = metas_xml.metadata.(#name == "Arguments");
for each (var argx:XML in args_xml.arg)
{
trace(argx.#value.toXMLString());
}
};
I use flex 4.6. Don't forget add each existing Metadata tags to the compiler argument with “-keep-as3-metadata+=Arguments”. It need for compile release versions.