var a = {
b: {
aa: 'hello',
bb: 'you',
cc: 'guys'
}
}
var b = function(){
$.each(a.b, function(x){
if( $.isFunction(x) == 'function' ){
alert(x);
};
});
};
var aa = function(){
var dude = 'hi there';
}
b();
I have an each loop inside the b function.
What i would like to do is loop through the a.b values, and find if a function exists with it's name. In this case the only one that should trigger is 'aa' as function 'aa exists.
is the isfunction line correct? or would typeof work?
In this case the only one that should trigger is 'aa' as function 'aa exists.
$.each() is iterating members of the Object passed to it. And, currently, the function aa is not a member of the Object a.b.
$.isFunction() isn't returning true because every member of a.b has a String value:
aa: 'hello',
bb: 'you',
cc: 'guys'
If you want the function as a member of the Object, you'll need to set it as the value of one of its properties:
a.b.aa = function () {
var dude = 'hi there';
};
This will replace the 'hello' value with a reference to the function.
To reuse the property names to lookup globals, you can use them on the global object (window in browsers).
var key = 'aa';
var val = window[key];
var b = function () {
$.each(a.b, function (key) {
if (key in window && $.isFunction(window[key])) {
alert(key + ' is a global function.');
}
});
};
Example: http://jsfiddle.net/cAaMf/
Though, note the "No wrap - in <body>" in the options of the Fiddle. This will only work for globals as no other scope object can be accessed within code.
Related
I wonder if there's a way to define a varibles to a function local [[Scopes]] for example the following function
//Parent function has a global scope {Window}
function x() {
//Local variable, closure to function {x}
var a = 123;
//Local function which have access to all {x} local scope like {a}
function y() {
console.log(a)
}
//Check the function y scope {window, Closure(x){a=123}
console.dir(y)
}
x()
the function above Scopes should to be like that
0: Closure (x) {a: 123}
1: Global {window: Window, self: Window, document: docume...
which can access window object and it's parent closures like a
another example for a local function which has 3 Scopes when using eval()
//Parent function has a global scope {Window}
function s(obj, fn) {
//Local variable and closure to {s} function
var q = 123
if (typeof fn === 'function') {
/*
- {y} here is local function which before {eval} have 2 scope
- {window}, closure (s) {obj: {a: "a", b: "b", c: "c"}, q = 123}
- after using of eval it's will get a new scope {block} scope Which will allow this function to access everything like obj, fn, y itself, q everything inside the parent function not just a Closure scope for things used on it like {q} and also it's will change
* closure (s) {obj: {a: "a", b: "b", c: "c"}, q = 123}
- to
* closure (s) {arguments: Arguments(2) [{…}, ƒ, callee: ƒ, Symbol(Symbol.iterator): ƒ], fn: ƒ (), obj: {a: "a", b: "b", c: "c"}, q: 123, r: 989
- the new closure will add everything even if it's not used on {y}
*/
function y(a) {
console.log(obj.a, q)
}
//That's will add a new scope to function {y} and change closure scope of it
eval('var r = 989')
//check {y} scope
console.dir(y)
}
}
s({
'a': 'a',
'b': 'b',
'c': 'c'
}, function() {console.log('i am a global function')})
the function y above have access to x arguments, vatiables, blocks like y function the Scope the of function above will be like that
0: Block (s) {defVar: ƒ}
1: Closure (s) {obj: {…}, q: 123, arguments: Arguments(2), fn: ƒ, defVar: ƒ, …}
2: Global {window: Window, self: Window, document: docume...
but if i have the following functions
//global function
//scrope = {window}
function x(fn) {
var q = 123;
//here's i want to define q var a local scope of {fn}
//like fn['[[Scopes]]']['1'] = 'Closure (x) {q: 123}' so when calling q from {fn} it's will return the q value i want to define it with the same name not like argument
console.log(fn())
};
//global function
//scrope = {window}
//i want to allow var q of {x} function to be used inside this function normally like
//function(){var t = "i'am a global function"; return t, q }
//the example above will return Uncaught ReferenceError: q is not defined
x(function(){var t = "i'am a global function"; return t, q })
2 functions above will be in the global scope window so is there's a way to add new scope to function something like fn['[[Scopes]]']['1'] = 'Closure (x) {q: 123}' or fn['[[Scopes]]']['1'] = x['[[Scopes]]']['1'] i know that [[Scopes]] cannot be accessed as property but it's just example
another example
// i want to do here the same at comments in example above
function x(fn) {
var q = 123;
y()
};
function y(){return 'str'}
is there's a way to set a new closures to the function y from function x like y['[[Scopes]]']['1'] = {a = 123, b = 456}
all i want to do is to set a local varibles to a function from another one or allow a global function to access cloures of another function
the last example to be more clear
the following function select html elements with presented key, value
i want when use the optional function to access the variables declared in selectElements method or define it to the optional function
HTML
<nav>
<ul class="nav-items">
<li class="nav-active">Home</li>
<li class="nav-item">Fruits</li>
<li class="nav-item">Veggies</li>
</ul>
</nav>
function selectElements(obj, fn) {
var sel = {
'class': function(el, arg) {
if (arg) {
return document.getElementsByClassName(el)
} else {
return 'document.getElementsByClassName("'+el+'")'
}
},
'id': function(el, arg) {
if (arg) {
return document.getElementById(el)
} else {
return 'document.getElementById("'+el+'")'
}
},
'tag': function(el, arg) {
if (arg) {
return document.getElementsByTagName(el)
} else {
return 'document.getElementsByTagName("'+el+'")'
}
}
}
if (typeof fn === 'function') {
var closureHanlder, text = ''
//console.dir(fn, defVar)
for(var i in obj) {
obj[i].replace(/^\./, function(elem) {
elem = obj[i].replace(/^\./, '');
elem = sel.class(elem);
text += 'var ' + i + ' = ' + elem + ';\n'
}).replace(/^\#+/, function(elem) {
elem = obj[i].replace(/^\#/, '');
elem = sel.id(elem);
text += 'var ' + i + ' = ' + elem + ';\n'
}).replace(/^\w+/, function(elem) {
if (!elem.startsWith('undefined')) {
elem = sel.tag(elem)
text += 'var ' + i + ' = ' + elem + ';\n'
}
})
}
console.log(text)
//decalre the elements with variables name
eval(text)
console.log(nav, navActive, navItem, navContainer)
// i want this function to get the declared elements as local variables or access them from this function {selectElements}
fn()
}
}
var el = {
'nav': 'nav',
'navActive': '.nav-active',
'navItem': '.nav-item',
'navContainer': '.nav-items'
}
selectElements(el, function () {
//here i want to access those varibles
//console.log(nav, navActive, navItem, navContainer)
// as a local varibles or access them from the function wheich used on it
})
To the best of my knowledge you can't. For starters [[Scopes]] is not a standard internal slot of any function object nor is it of ANY object for that matter. So at best you would be looking at a solution for Chrome only and it most certainly wouldn't be available through javascript.
There's also very little to be gained here. The function wouldn't know about what other variables you are including into its scope. If you are hoping to add a scope that's constant then there's no point to it either since you could just add the respective declarations to the respective function.
This is why with failed to provide any real value while also making you question whether any identifier is also being shadowed by the new dynamic context.
I meet a problem about dynamic dispatch. The following is the code snippet which from the book [Programming JavaScript Applications], and I put it on https://jsfiddle.net/abramhum/bbfxxwok/1/
function equals(a, b, c) {
console.log("a[=]" + a);
if (a == b) {
console.log(c);
}
}
function test(a, fn) {
console.log(a + " ---start function[=]");
fn.apply(this);
console.log(a + " ---Fnished");
}
var methods = {
init: function(args) {
return 'initializing...';
},
hello: function(args) {
return 'Hello, ' + args;
},
goodbye: function(args) {
return 'Goodbye, cruel ' + args;
}
},
greet = function greet(options) {
var args = [].slice.call(arguments, 0),
initialized = false,
action = 'init'; // init will run by default
if (typeof options === 'string' &&
typeof methods[options] === 'function') {
action = options;
args.shift();
}
return methods[action](args);
};
test('Dynamic dispatch', function() {
var test1 = greet(),
test2 = greet('hello', 'world!'),
test3 = greet('goodbye', 'world!');
equals(test2, 'Hello, world!',
'Dispatched to hello method.');
equals(test3, 'Goodbye, cruel world!',
'Dispatched to goodbye method.');
});
There exist two subjects in this problem, one is when greet("goodbye", "world") is executed, why it called greet(options), and the value about options is indeed the fist parameter, like "goodbye", and the "world" can be get via arguments; The second is var methods ={...}, it get the arguments like init, and return the value if matching the declare, like init:function(args){...}, but it indeed not code style of switch, and why we can use that in javascript.
This is much unlike C codes, I don't know why, is any one know the reason?
thanks.
one is when greet("goodbye", "world") is executed, why it called greet(options), and the value about options is indeed the fist parameter, like "goodbye", and the "world" can be get via arguments
Because in a JavaScript non-arrow function, arguments is a predefined identifier referring to a pseudo-array of all of the arguments passed to the function. It has nothing to do with dynamic dispatch. It's just a feature of JavaScript functions that was useful back before JavaScript got proper variable parameter lists:
function foo() {
console.log("foo called, total arguments: " + arguments.length);
for (var n = 0; n < arguments.length; ++n) {
console.log("Arg #" + n + ":", arguments[n]);
}
}
foo();
foo("bar");
foo("biz", 42);
the second problem is var methods ={...}, it get the arguments like init
Those aren't arguments, those are properties being defined for the object assigned to methods. Just like a, b, and c here:
var obj = {
a: 42,
b: "Whatever",
c: "just cuz"
};
...and return the value if matching the declare, like init:function(args){...}, but it indeed not code style of switch, and why we can use that in javascript.
Because functions are objects, and so like any other object, you can refer to them from variables, arguments, and object properties. methods's properties init, hello, and goodbye refer to functions. You can call them via the properties: method.init().
So say we have the variable name containing "init". We can look up the property with that name on methods: methods[name]. And since that gives us a reference to a function, we can call that function.
var methods = {
init: function() {
console.log("init called");
}
};
var name = "init";
methods[name](); // "init called"
More: Dynamically access object property using variable
This is much unlike C codes, I don't know why, is any one know the reason?
Because C and JavaScript are fundamentally different languages, created with different design constraints, at different times, by different people, with different priorities and limits.
let us say i have a object in which there is a function and inside the function i have declared some key values.
if every function is an function object in javascript then it is totally legal to declare key value pair in it.
var a ={
a: "shiv",
b: "shiv1",
c: function(){
L:"shiv1",
console.log(L);
}
}
how can i access these keys. in what scenarios i need to add key value pairs to a function. what does this signify. For Example in this function, how can i access L key.
Edit 1:
Console.log line will through err.
let say we have only this code
var a ={
a: "shiv",
b: "shiv1",
c: function(){
L:"shiv1",
}
}
what does declaring a key in function signify. if i need to access L key how can i
You every function is also an object, meaning that you can indeed set properties to it. In fact every function has length property, which denotes the number of formal arguments this function accepts.
However the syntax you are using to set function properties is not how you should do it. Even though you are using perfectly valid syntax, this is label statement, not property definition syntax. If you wanted to set a property to a function object in your case you would do it like this:
function c() {
console.log(c.L) // => "I'm a property of c function"
}
c.L = "I'm a property of c function";
var a = {
a: "shiv",
b: "shiv1",
c: c
}
When it can be useful? Like I said there is a limited use for it, like length property of the function, but in many cases you would not need setting properties on a function level directly.
This has to be throwing errors:
L:"shiv1",
console.log(l);
You probably want:
c: function(){
return {L:"shiv1"};
}
And then access it as:
a.c().L;
Full example here:
var a ={
a: "shiv",
b: "shiv1",
c: function(){
return {L:"shiv1"}
}
}
alert(a.c().L);
You can't declare keys like you did inside the function.
This doesn't work:
c: function(){
L:"shiv1", //Declaration don't work in this context
console.log(l); //Don't work
}
Try this (Please, remove the "function" statement):
c: {
L:"shiv1"
}
Also, you can do this:
c: function() {
var test = "shiv1";
return test;
}
If you want to work with parameters:
c: function(a, b) {
var test = a + " shiv1 " + b;
return test;
}
Or:
c: function(a, b) {
var total = a + b;
return total;
}
Given the code with a closure, why is make_function returning null when I pass it an object?
Plnkr: http://plnkr.co/edit/L3nNeiibTMdR6GEnyMOX?p=preview
$(document).ready(everything);
function everything() {
var null_start = null;
var object_start = { obj: null };
function make_function (arg) {
return function () {
d3.select('#console')
.append('p')
.text(JSON.stringify(arg))
.style('color', 'blue');
};
}
// Make a function with arg=null
var func = make_function(null_start);
d3.select('#console').append('p').text('Expecting null here');
func();
null_start = {
foo: 5,
bar: 42
};
d3.select('#console').append('p')
.html('Expecting {foo:5, bar:42} here <span style="color:red;">Why is this still null???</span>');
func();
// Make a function with arg={obj:null}
func = make_function(object_start);
d3.select('#console').append('p').text("Expecting {obj: null} here");
func();
object_start.obj = {
foo: 5,
bar: 42
};
d3.select('#console').append('p')
.html('Expecting {obj: {foo:5, bar:42}} here <span style="color:red;">if this one is updated?</span>');
func();
}
Arguments passed in JavaScript are not passed by reference, but by a special "reference-copy". In other words, when you pass null_start to make_function, a copy of the null_start variable is passed.
Changes to the null_start variable would not be reflected by the variable passed to the function.
This is the reason why creating another function with the new value of the variable works as intended in your example.
Note that when passing objects, changes to the object will be reflected by the original variable as well. This is because objects are mutable in JavaScript. For example:
function change (obj) { obj.foo = 'bar'; }
var x = {};
change(x);
console.log(x.foo); // 'bar'
This is because an object is merely a box of keys pointing to values. Keys inside the object point to values, which can be modified, and reflected upon by the outer-scope of the function. But if we pass the value directly, it will not work:
function change (val) { val = 'fff'; }
var x = {foo: 'bar'};
change(x.foo);
console.log(x.foo); // 'bar'
Hope that helps!
i want to run a function, inside another function dynamically...
let say :
<script>
var x = function(r,s){
r(s);
}
var a = function(item){
alert("aA");
}
var b = function(item){
alert("bB");
}
</script>
is this possible?
i take "r" from function x's argument as a function name, and i want to run it.
if r=a, then it will trigger function a()
and if r=b, function b triggered instead...
how could i do that?
You could simply test r and call each function as needed.
if (r === 'a') {
a(s);
} else if (r === 'b') {
b(s);
}
Or, if you have many functions for this or don't always know them all ahead of time, you can organize them in an Object and use bracket operators to treat r as a key name to access them:
var commands = {
a: function(item){
alert("aA");
},
b: function(item){
alert("bB");
}
};
var x = function (r, s) {
var command = commands[r];
if (typeof command === 'function') {
command(s);
}
};
x('a', 'foo'); // alerts `aA`
Or, even just pass a and b as the arguments themselves with your current definition of x().
x(a, 'foo'); // calls `a` as `r`, passing 'foo' along
By passing the name of the function as the first parameter to x when calling it.
x(a, {}); // alert("aA");
x(b, {}); // alert("bB");
Note that you're passing the reference to the function, not a string. This is because functions in JavaScript are objects and are passed by reference, not by value. So var a = function() {...}; actually means that variable a holds a reference to the function.
you mean like:
var x = function(r,s){
window[r](s);
}
var a = function(item){
alert("aA");
}
var b = function(item){
alert("bB:" + item);
}
x('b', 'test');