Code:
var test = {
con: true
};
var conrun= function(){
return this.con;
};
Function.prototype.curry = function(scope){
var fn = this;
var scope = scope||window;
return function(){
fn.apply(scope,arguments);
}
}
conrun = conrun.curry(test);
alert(conrun());
//result:undefined
"curry" method, the function will return, "conrun" fonkiyonuna "test" add to the scope of...
What should I do ?
Your curry loses the return value. Change that line to:
return fn.apply(scope, arguments);
Related
I picked up some code and I am just getting to understand the new Function();. Going through jslint the new Function(); was highlighted as unexpected. I started to experiment with it doing the following.
var func = new Function();
func.property = "some property";
return func;
A replacement.
var func = new function(){
this.property = "some property";
}
return func;
Both work and the second one is neglected by js-lint.
Am I doing anything spectacular here, or is this exactly the same? Is it syntactical correct to use new Function(); like this?
Original code excerpt is attached.
var $ = (function() {
function doCSS(prop, val) {
var isSet = Boolean(val),
action = CSSStyleDeclaration.prototype.setProperty,
args = arguments;
if (isSet) {
this.each(function(node, i) {
action.apply(node.style, args);
});
return this;
} else if (typeof(prop) === 'object') {
this.each(function(node, i) {
Object.keys(prop).forEach(function(property) {
node.style[property] = prop[property];
});
});
return this;
} else {
return this.nodes[0].style[prop];
}
}
// chaining of methods
return (function(selector, context) {
var q = new Function();
q.selector = selector;
q.context = context || document;
q.nodeList = q.context.querySelectorAll(selector);
q.each = function(action) {
[].forEach.call(q.nodeList, function(item, i) {
action(item, i);
});
return this;
};
q.click = function(action) {
[].forEach.call(q.nodeList, function(item, i) {
item.addEventListener("click", action, false);
});
return this;
};
q.toString = function() {
return q.selector;
};
q.css = function(prop, val) {
return doCSS.call(this, prop, val);
};
return q;
});
})
Is any of these two wrong in syntax?
EDIT
After getting some of the great advice I adapted the code to the following:
var $ = (function($) {
function doCSS(prop, val) {
var isSet = Boolean(val),
action = CSSStyleDeclaration.prototype.setProperty,
args = arguments;
if (isSet) {
this.each(function(node, i) {
action.apply(node.style, args);
});
return this;
} else if (typeof(prop) === 'object') {
this.each(function(node, i) {
Object.keys(prop).forEach(function(property) {
node.style[property] = prop[property];
});
});
return this;
} else {
return this.nodes[0].style[prop];
}
}
// chaining of methods
return (function(selector, context) {
var element = context || document;
var q = {
selector: selector,
nodeList: element.querySelectorAll(selector),
each: function(action) {
[].forEach.call(this.nodeList, function(item, i) {
action(item, i);
});
return this;
},
click: function(action) {
[].forEach.call(this.nodeList, function(item, i) {
item.addEventListener("click", action, false);
});
return this;
},
toString: function() {
return selector;
},
css: function(prop, val) {
return doCSS.call(this, prop, val);
},
}
return q;
});
})($);
$("#myElement").css({
background: "blue",
color: "#fff"
});
<div id="myElement">Say Hi</div>
It works just fine and looks a lot cleaner. JS Lint is nice to me and I can tackle the next issue.
In the first case, you create a new object and you apply the Function constructor.
Return value is a function.
In the second example, you create a new object and you apply an anonymous function as constructor.
Return value is an object.
Both statements are indeed different. I will focus on the second statement to point out the difference.
var newObj1 = new function () {
this.prop1 = "test1";
this.prop2 = "test2"
};
Is equivalent to the following:
var Example = function () {
this.prop1 = "test1";
this.prop2 = "test2"
};
var newObj2 = new Example();
The only difference being that in the first example the constructor function called is an anonymous function. Note, that when a function is called with the new keyword in javascript it exhibits special behavior.
In your first statement the constructor function called is an already defined function, Function.
As has been pointed out your first statement returns a function while the second returns an object. Neither, is wrong but one returning a function and the other an object could have implications in other sections of your code.
Yes it is not right approach to create objects
because objects created through new Function() are less efficient than the functions created using function expression
The global Function object has no methods or properties of its own, however, since it is a function itself it does inherit some methods and properties through the prototype chain from Function.prototype
for more reference
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function
Hope this helps
Check the following code snippet
var func = new Function();
func.property = "some property";
"some property"
console.log(func);
now when you check in the console it says it as anonymous
but when an object created through function expression
var func=new function(){this.x=10;}
console.log(func);
this returns an objects
I guess you understand the difference
What is the difference between this way:
var MyNamespace = window.MyNamespace || {};
MyNamespace.Helper = function()
{
var _getValue = function()
{
var value = 5;
return value;
};
return
{
getValue: _getValue
};
}();
and this way:
var MyNamespace = window.MyNamespace || {};
MyNamespace.Helper = function()
{
function _getValue()
{
var value = 5;
return value;
};
var publicMethod =
{
getValue: function() { _getValue(); }
};
return publicMethod;
};
There are two pretty significant differences:
The first version doesn't return an object, so MyNamespace.Helper will be undefined. Trying to use getValue on it will fail. This is thanks to Automatic Semicolon Insertion adding a ; after the return. Don't put line breaks after return and what it returns.
Assuming you fix that, then calling MyNamespace.Helper.getValue on the first one will give you the value 5, whereas calling it on the second one will give you undefined, because your anonymous wrapper around _getValue doesn't return anything.
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Javascript outer scope variable access
I have a javascript module that looks something like below. The main issue I'm having is how to access variables in the "this" scope from the private someOtherFunc. Is there a way to access this.myvar in the private someOtherFunc
var mymodule = (function(){
return {
MyObj : function() {
this.myvar = 123;
this.publicfunc = function() {
someOtherFunc();
};
var someOtherFunc = function() {
//this doesn't seem to work
this.myvar = 456;
};
}
}
}
The idea is that I want to be able to do something like
new mymodule.MyObj().publicfunc, but make the someOtherFunc private
Forget my previous answer. You can do this just by adding a private version of this.
var mymodule = (function() {
return {
MyObj : function() {
this.myvar = 123;
var that = this;
this.publicfunc = function() {
someOtherFunc();
};
var someOtherFunc = function() {
that.myvar = 456;
};
return this;
}
};
});
Bear in mind that, with your code, every time you call MyObj you get a new object.
So this would do what you want:
>var o = new mymodule().MyObj()
>o.myvar
123
>o.publicfunc()
>o.myvar
456
but not this
>var m = new mymodule()
>m.MyObj().myvar
123
>m.MyObj().publicfunc()
>m.MyObj().myvar
123
If that's not what you want, consider doing something like this
var mymodule = (function() {
var myObj = null;
this.MyObj = function() {
if(myObj != null)
return myObj;
myObj = {};
myObj.myvar = 123;
myObj.publicfunc = function() {
someOtherFunc();
};
var someOtherFunc = function() {
myObj.myvar = 456;
};
return myObj;
};
});
Declare myvar using the var keyword, making it private, then access it without the this.:
function MyObj(){
var myvar = 123;
this.publicfunc = function() {
someOtherFunc();
};
var someOtherFunc = function(){
alert(myvar);
};
}
var o = new MyObj();
o.publicfunc();
If you need public access to myvar then create a public getter/setter.
jsFiddle Demo
I think what you're looking for is a way to encapsulate myvar for changes. When some of the other answers run, myvar usually will stay as 123 because the initially returned object from mymodule holds on to that initial value.
Return a function that gets the value of myvar even after it's been modified, and I think that helps your problem.
Here's the code that works for me:
var mymodule = (function(){
var myvar = 123,
publicfunc = function() { myvar = 456 },
getMyVar = function() { return myvar; };
return {
someOtherFunc : publicfunc,
myPublicVar : getMyVar
};
}());
mymodule.someOtherFunc();
alert(mymodule.myPublicVar()); //gives you 456
JSFiddle here.
I hope this helps.
Why not build it a little more deliberately?
// this one returns an object used like:
// myModule.myInt; /* 456 */
// myModule.myFunc(); /* 124 */
var myModule = (function () {
var secretData = 123,
publicData = 456,
publicFunc = function () { return privateFunc(secretData); },
privateFunc = function (num) { return num + 1; },
public_interface = {
myInt : publicData,
myFunc : publicFunc
};
return public_interface;
}());
I went through the trouble of explicitly naming the returned, public object, but it's now very clear what is and isn't public, and yet, each one of those things will have access to the variable versions of one another, with the one exception being that if you change myModule.myInt or publicData, they will no longer be equal.
To demonstrate what I mean in the comments below, creating multiple instances with their own private data/methods, I just add in one more layer of function-scope:
var myModule = (function () {
var static_int = 789,
makeInstance = function (/* any constructor values */) {
var secretData = 123,
publicData = 456,
publicFunc = function () { return privateFunc(secretData); },
privateFunc = function (num) {
console.log(static_int);
return num + 1;
},
public_interface = {
myInt : publicData,
myFunc : publicFunc
};
return public_interface;
};
return makeInstance;
}());
You now use it like:
var newModule = myModule(/* instance parameters */);
newModule.myFunc();
...or
var num = myModule(/* instance parameters */).myFunc();
If you wanted to save memory, you could have static helper functions inside of the static-layer:
var myModule = (function () {
var static_int = 789,
static_addOne = function (num) { return num + 1; },
static_divideBy = function (dividend, divisor) { return dividend/divisor; },
makeInstance = function (/* any constructor values */) {
var secretData = 123,
publicData = 456,
publicFunc = function () { return privateFunc(secretData); },
privateFunc = function (num) {
console.log(static_int);
return num + 1;
},
public_interface = {
myInt : publicData,
myFunc : publicFunc
};
return public_interface;
};
return makeInstance;
}());
And now you have "private" functions which are only written one time (ie: you save memory), but any instance can use those functions.
Here's the catch:
Because of how scope and closure work, the static functions have NO access to values inside of the instance (functions inside have access to the static functions, not the other way around).
So, any static helper functions MUST have the values passed to them as arguments, and if you're modifying a number or a string, you MUST return the value out of that function.
// inside of a private method, in any instance
var privateString = "Bob",
privateFunc = function () {
var string = static_helper(privateString);
privateString = string;
//...
};
You don't return anything from MyObj.
return this;
should fix it.
Use the bind method:
var someOtherFunc = function() {
this.myvar = 456;
}.bind(this);
How could I do this?
Class
var Factory = (function() {
var Class = function() {
this.name = 'John';
this.methods = {
get: function(callback) {
callback();
}
};
};
return {
createClass: function() {
return new Class();
}
};
}());
Usage
var MyClass = Factory.createClass();
MyClass.methods.get(function() {
this.name // => returns undenfined
});
Thanks for any help!
You need to save a reference to this in the outer Class function and call call:
var instance = this;
this.methods = {
get: function(callback) {
callback.call(instance);
}
};
var Class = function() {
// Save a reference to this that can be used in local closures.
var me = this;
this.name = 'John';
this.methods = {
get: function(callback) {
// Use 'call()', passing the reference to the 'Class' object
callback.call(me);
}
};
};
#SLaks - The declaration of scope as a Global variable is bad practice.
#Ferdinand Beyer - have you tested if it functions?
The better way will be the scope binding. The Prototype javascript framework produced a nice concept and we can easily implement it like
Function.prototype.bind = function(scope) {
var _function = this;
return function() {
return _function.apply(scope, arguments);
}
}
and then yoou code should have only a single change and it will maintin the scope of your class.
var Factory = (function() {
var Class = function() {
this.name = 'John';
var me = this;
this.methods = {
get: function(callback) {
callback();
}
};
};
return {
createClass: function() {
return new Class();
}
};
}());
var MyClass = Factory.createClass();
MyClass.methods.get(function() {
console.info(this.name) // => returns undenfined
}.bind(MyClass));
I mean only the function call get with .bind(MyClass)
I know you can create literal objects with subobjects and functions:
var obj = {
val : 1,
level1 : {
val : 2,
val2 : 3,
func : function(){
return this.val2
}
}
}
console.log(obj.val);
console.log(obj.level1.val);
console.log(obj.level1.func());
outputs:
1
2
3
What I would like to do is do the same thing with methods in a object, something similar to:
function objType() {
this.val = 1;
this.func = function(){
return this.val;
}
this.level1 = function(){
this.val = 2;
this.func = function(){
return this.val;
}
this.level2 = function(){
this.val = 3;
this.func = function(){
return this.val;
}
}
};
};
then i would expect:
var obj = new objType();
console.log(obj.func());
console.log(obj.level1.func());
console.log(obj.level1.level.func());
to output:
1
2
3
However, only the first console.log outputs before the script throws an error.
Is there any way to have sub methods in Javascript?
--edit--
My goal is to create a class i can use for showing a box in the middle of the screen, for displaying messages, questions(to get a yes/no response), and forms. I was thinking a good way to structure it would be with sub methods, so that it could then be referenced with:
function box() {
this.show = function(){
//multiple sub methods here
}
this.hide = function(){
//code to hide window here
}
}
var aBox = new box();
aBox.show.message('the message');
aBox.hide();
aBox.show.question('the question');
aBox.hide();
--edit--
thanks #Sean Vieira
For completeness I'll put the modified version of my code here using his solution:
function objType() {
this.val = 1;
this.func = function(){
return this.val;
}
this.level1 = {
val : 2,
func : function(){
return this.val;
},
level2 : {
val : 3,
func : function(){
return this.val;
}
}
}
var obj = new objType();
console.log(obj.func());
console.log(obj.level1.func());
console.log(obj.level1.level.func());
that outputs
1
2
3
you can do this easily with chaining
function Box() {
this.show = function(){
//your code goes here
return this;
},
this.message = function(message){
//code goes here
return this;
}
}
var aBox = new Box();
aBox.message('the message').show()
Your issue is that this in JavaScript refers to the containing scope -- which in the case of a function invoked with the new operator is a new Object and this applies everywhere within the scope of that function (unless you create a new scope in some way.)
So in your code we can replace this with an imaginary "new" object ... let's call it that.
function objType() {
var that = {}; // This is what `new` does behind the scenes
// (Along with a few other things we won't replicate here).
that.val = 1;
that.func = function(){
return that.val;
}
// Do additional things with `that` here
return that;
}
However, whenever you deal with a function that you are not calling as a "class" (as in a free-standing function or a "method" of an object) then this is set dynamically at runtime.
This means that:
function log_this() {
console.log(this,
"Type:", typeof this,
"IsObject:", this instanceof Object,
"IsFunction:", this instanceof Function);
}
log_this() // window (i.e. global scope)
log_this.apply({"some":"object"}) // {"some":"object"}
log_this.apply(function(){}) // Anonymous function function(){}
var test_object = { fun: log_this };
test_object.log_this() // test_object
This might work for level1:
var obj2 = new obj.level1();
console.log(obj2.func());