Need help reaching a variable in JavaScript - javascript

Can someone please help me understand the scoop of JavaScript variables, and how to reach them?
Imagine the following...
// Namespace declaration
var p = {};
p.result = {
searchForm: $('#search-form'),
searchAction: this.searchForm.attr('action'),
anotherSection: {
hello: 'Hello ',
world: this.hello + 'world!'
}
}
This won't work, and it gives the error saying this.searchForm is undefined. The same error appears in anotherSection as well (ofc).
How can I declare a variable in terms of another variable inside the same namespace?

The this keyword is bound to the function-context, you can't use it in object literals like that.
You could, make functions as "getters":
var p = {};
p.result = {
searchForm: $('#search-form'),
getSearchAction: function () {
return this.searchForm.attr('action');
},
anotherSection: {
hello: 'Hello ',
getWorld: function () {
return this.hello + 'world!';
}
}
};

There is no way to refer to an object literal as you're building it.
You need to write the following:
p.result = {
searchForm: $('#search-form'),
anotherSection: {
hello: 'Hello '
}
}
p.result.searchAction = p.result.searchForm.attr('action');
p.result.anotherSection.world = p.result.anotherSection.hello + 'world!';

You can't access the properties of an object inside its own literal — they don't exist yet.

this is an object, so when you use this.searchForm, you are accessing a property of the this object. You just want to access a variable, so you can just use searchForm.

Related

JavaScript Define Property in Terms of Method

Please note this question is not answered by
Self-references in object literals / initializers
as that question addresses defining properties in terms of other properites, not methods.
Also, How does the "this" keyword in Javascript act within an object literal? is too high-level a decription of the subject for me to be able to solve my use case.
In Python, I can do this:
class Test:
def __init__(self):
self.id = self.get_id()
def get_id(self):
return 10
t = Test()
print(t.id)
Meaning an object property can be defined in terms of a method of the same object.
In JavaScript, it doesn't work:
var Test = {
id : this.getId(),
getId : function() {
return 10;
}
};
Gives script.js:47 Uncaught TypeError: this.getId is not a function
I've tried defining the id after the method definition but that didn't work.
How do I do this in JavaScript please?
The other answer (Evgeny Yudin) is simpler - but this is an alternative using classes that may add something to your understanding.
class Test {
constructor() {
this.id = this.getId();
}
getId() {
return 10;
}
}
console.log((new Test()).id); //outputs 10
var Test = {
get id() {
return 10
}
}
console.log(Test.id)
https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Functions/get
or
var Test = {
get id () {
return this.getId()
},
getId: function () {
return 10
}
}
console.log(Test.id)
You can only use this inside a method. There's no way to reference the current object in an object literal.
But you can refer to it after the object is created.
var Test = {
getId : function() {
return 10;
}
};
Test.id = Test.getId()

Not able to access namespace variable in js file

a.js
// #global-constants
var App = {
constant: function() {
constant.prototype.CONST1 = 'abc';
}
};
module.exports = App;
not able to access in say b.js using App.constant.CONST1, it says undefined why?
there are two problems with you code:
1.) App.constant would return a class(technically a function), but what you want is it's object, can be created using a new keyword, so it becomes, (new App.constant).CONST1.
2.) constant.prototype.CONST1 would not work, because constant is not the name of your anonymous function, so I gave it a name foo and it becomes foo.prototype.CONST1.
the modified code:
var App = {
constant: function foo() {
foo.prototype.CONST1 = 'abc';
}
};
console.log((new App.constant).CONST1);
fiddle demo.
If you just want to create a set of "constants", all you need is an object:
// #global-constants
var App = {
constant: {
CONST1: 'abc';
}
};
To learn more about how prototypes work (so that you know when to use them and when not), I recommend to read this article on MDN.

Extending object literal

var x = {
name: "japan",
age: 20
}
x.prototype.mad = function() {
alert("USA");
};
x.mad();
The above code does not work.
object literals cannot be extended? or x.mad() not the right way to call.
You can't do it this way. To be able to define object methods and properties using it's prototype you have to define your object type as a constructor function and then create an instance of it with new operator.
function MyObj() {}
MyObj.prototype.foo = function() {
// ...
}
var myObj = new MyObj();
myObj.foo()
If you want to keep using object literals, the only way to attach behaviour to your object is to create its property as anonymous function like so
var myObj = {
foo: function() {
// ...
}
}
myObj.foo();
The latter way is the quickest. The first is the way to share behaviour between mutiple objects of the same type, because they will share the same prototype. The latter way creates an instance of a function foo for every object you create.
Drop the prototype.
Replace:
x.prototype.mad = function() {
With:
x.mad = function() {
This simply adds a mad property to the object.
You dont have .prototype available on anything but function object. So your following code itself fails with error TypeError: Cannot set property 'mad' of undefined
x.prototype.mad = function() {
alert("USA");
};
If you need to use prototype and extension, you need to use function object and new keyword. If you just want to add property to your object. Assign it directly on the object like following.
x.mad = function() {
alert("USA");
}
x.constructor.prototype.mad = function() {
alert("USA");
};
x.mad();
This also works, by the way:
Object.prototype.mad = function() {
alert("USA");
}
var x = {
name: "japan",
age: 20
}
x.mad();
But then, the mad function will be part of any object what so ever,
literals, "class" instances, and also arrays (they have typeof === "object").
So - you'll probably never want to use it this way. I think it's worth mentioning so I added this answer.

JavaScript: Traversing/navigating through a namespace from within a namespace?

I'm new to javascript namespaces, and I found myself kinda deep within a namespace, but unable to find a way to navigate from within the namespace to another object in the same general namespace. It's best described by the code below:
$.fileUploading = {
images: {
settings: {
// How do you do this?
bing_bong: find.a.way.to.functionOne
},
functionOne: function() { return "Rock!"; }
}
}
Is there a way to do that?
Because namespaces are just properties on objects, there's no way to find out what object a property belongs to, from the property. A simple reason is that an identical property can appear in multiple objects.
Namespaces are supposed to be stable and constant, so there's nothing wrong with referencing the entire thing. However, if you need to access the same names a ton of times, you could make it a bit easier for yourself by assigning it to a variable.
var my_ns = $.fileUploading;
This would work:
$.fileUploading = {
images: {
settings: {},
functionOne: function() { return "Rock!"; }
}
};
$.fileUploading.images.settings.bing_bong = $.fileUploading.images.functionOne;
This also:
function f() { return "Rock!"; }
$.fileUploading = {
images: {
settings: {
// How do you do this?
bing_bong: f
},
functionOne: f
}
};
(function(){
var yourNameSpace={
publicProp1:publicFn1,
publicProp2:publicFn2,
publicProp3:publicFn3
};
window.yourNameSpace = yourNameSpace;
//private variable
var _privateVar1,_privateVar2,_privateVar3;
//privatefns
function _privateFn1(){}
function _privateFn2(){}
function _privateFn3(){}
function _privateFn4(){}
//public functions can access private fns
function publicFn1(){}
function publicFn2(){}
function publicFn3(){}
}(undefined);

Call a JavaScript function name using a string?

How can I hook up an event to a function name I have defined as a string?
I'm using Prototype.js, although this is not Prototype-speficic.
$(inputId).observe('click', formData.fields[x].onclick);
This would result in JavaScript complaining that my handler is not a function. I would prefer not us use eval().
Property accessors can be used to access any object's properties or functions.
If the function is in the global scope, you can get it using the window object:
var myFunc = window[myFuncName];
This also works within the this scope:
var myFunc = this[myFuncName];
I have worked on this problem, as I needed a function like this. Here is my sandbox code, not thoroughly tested, but can be a startpoint for others.
Note that there is one eval() in the code as I couldn't figure out how to bypass that step, maybe a javascript quirk and cannot be done in any other way. Let me know if there is a way to get rid of eval() here!
executeFunctionByName = function(functionName)
{
var args = Array.prototype.slice.call(arguments).splice(1);
//debug
console.log('args:', args);
var namespaces = functionName.split(".");
//debug
console.log('namespaces:', namespaces);
var func = namespaces.pop();
//debug
console.log('func:', func);
ns = namespaces.join('.');
//debug
console.log('namespace:', ns);
if(ns == '')
{
ns = 'window';
}
ns = eval(ns);
//debug
console.log('evaled namespace:', ns);
return ns[func].apply(ns, args);
}
core = {
paragraph: {
titlebar: {
user: "ddd",
getUser: function(name)
{
this.user = name;
return this.user;
}
}
}
}
var testf = function()
{
alert('dkdkdkd');
}
var x = executeFunctionByName('core.paragraph.titlebar.getUser', 'Ikon');
executeFunctionByName('testf');
... or this[myFuncName];
Perhaps?
setTimeout ( "myFunc()", 1 );
Just an eval would do the job
var call = eval("method_name").call(args);
Looks like formData.fields[x].onclick holds the name of a global function? If so try:
$(inputId).observe('click', window[formData.fields[x].onclick]);
window.myFunction === window["myFunction"]
Do you know what the onclick property contains or what type it is? I assume this is prototype specific stuff, as "fields" does not exist in DOM forms.
If you need to call a string function with arguments, do this:
window[stringFunctionName].apply( window, arrayOfArguments )
You can use scope in place of window if preferred
update:---
use ES6 export and import
a.js
const fn = {
aaa: function() {
//code
},
bbb: function() {
//code
},
//codes ....
nnn: function() {
//code
}
}
export default fn
b.js
import someFn from './a'
//eg
const str1='aaa'
const str2 = 'bbb'
someFn[str1]()
eval('str') (obsolete feature https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Deprecated_and_obsolete_features )
setTimeout('str') setInterval('str')
window['str'] (but...sometimes,global object is not window)
new Function('str')
These methods above always not be recommend by some reasons, but they are really convenient to use.
These methods below are safe, but really not conveninet to use.
switch...case (or if...else)
switch(str){
case 'str1':
fn1()
break
case 'str2':
fn2
//and so on
}
put functions in a object
const fn={
str1:fn1,
str2:fn2
//and so on
}
fn[str1] //call function

Categories