Invoke method in JavaScript - javascript
Out of the following 2 ways of calling a method in JavaScript;
myFunc(params);
obj.myFunc();
My questions are;
For each of them, what exactly is the difference in accessing the values (for params/obj) inside myFunc()
For the 1st case, when we use "this" inside myFunc(), it would refer to global obj (window). What about the second case?
What are the use cases for using either of the 2 techniques?
You can add any other significant differences between the two techniques as well.
Since you did not provide enough context, I will assume your two function calls:
1. myFunc(params)
2. obj.myFunc()
correspond to the following definitions of myFunc() and obj.myFunc():
function myFunc(params) { }
var obj = {
myFunc: function() { }
};
The first call myFunc(params) is a call to the global function myFunc() with params passed as the parameter. this will refer to the global object, which is window inside browsers (You can test this by doing window.myFunc === myFunc, which will return true)
The second call obj.myFunc() is call to the method myFunc() inside the obj object. this will refer to obj, not window.
Regarding use cases, that will depend on your design, but global functions are obviously not recommended as they pollute the global namespace (i.e. you may redefine the global myFunc() by accident without noticing it).
The second approach is common when you need a pseudo javascript namespace
I will re-render your questions:
3- Cases: your_obj.function(): this one is usually used in the single page web app or you have many module one one page and you want to separate modules for maintaining purposes. While myfunction(args) is a global usage.
2 - you can invoke it by: window.your_obj.function()
1 - I'm not sure what you mean :)
Those are my opinion.
Related
What is difference between function FunctionName(){} and object.FunctionName = function(){}
Today while working my mind was stack at some point in javascript. I want to know that what is basic difference between function FunctionName(){ //Code goes here; } And var MyFuncCollection = new Object(); MyFuncCollection.FunctionName = function(){ //Code goes here; } Both are working same. Then what is difference between then. Is there any advantage to use function with object name? I have read Question. But it uses variable and assign function specific variable. I want to create object and assign multiple function in single object.
The first one defines a global function name. If you load two libraries, and they both try to define FunctionName, they'll conflict with each other. You'll only get the one that was defined last. The second one just has a single global variable, MyFuncCollection. All the functions are defined as properties within that variable. So if you have two collections that try to define the same function name, one will be FuncCollection1.FunctionName, the other will be FuncCollection2.FunctionName, and there won't be any conflict. The only conflict would be if two collections both tried to use the same name for the collection itself, which is less likely. But this isn't totally unheard of: there are a few libraries that try to use $ as their main identifier. jQuery is the most prominent, and it provides jQuery.noConflict() to remove its $ binding and revert to the previous binding.
The short answer is, the method in object context uses the Parent Objects Context, while the "global" function has its own object context. The long answer involves the general object-oriented approach of JavaScript, though everything in JavaScript is an object you may also create arrays with this Method. I can't really tell you why, but in my experience the best function definition is neither of the top mentioned, but: var myFunction = function(){}; It is possible to assign function to variables, and you may even write a definition like this: MyObject.myMethod = function(){}; For further reading there are various online Textbooks which can give you more and deeper Information about this topic.
One main advantage I always find is cleaner code with less chance of overwriting functions. However it is much more than that. Your scope changes completely inside the object. Consider the following code :: Function: function FunctionName(){ return this; } FunctionName() Returns: Window {top: Window, location: Location, document: document, window: Window, external: Object…} Object: var MyFuncCollection = new Object(); MyFuncCollection.FunctionName = function(){ return this; } MyFuncCollection.FunctionName() Returns: Object {} This leads to some nice ability to daisy chain functions, amongst other things.
The first: function functionName (){ //Code goes here; } Is a function declaration. It defines a function object in the context it's written in. Notice: this doesn't have to be the global context and it doesn't say anything about the value of this inside it when it's invoked. More about scopes in JavaScript. Second note: in most style guides functions are declared with a capitalized name only if it's a constructor. The second: var myFuncCollection = {}; myFuncCollection.functionName = function () { //Code goes here; }; notice: don't use the new Object() syntax, it's considered bad practice to use new with anything other then function constructors. Use the literal form instead (as above). Is a simple assignment of a function expression to a property of an Object. Again the same notice should be stated: this says nothing about the value of this when it's invoked. this in JavaScript is given a value when the function object is invoked, see here for details. Of course, placing a function on an Object help avoiding naming collisions with other variables/function declarations in the same context, but this could be a local context of a function, and not necessarily the global context. Other then these differences, from the language point of view, there's no difference whatsoever about using a bunch of function declarations or an Object with bunch of methods on it. From a design point of view, putting methods on an Object allows you to group and/or encapsulate logic to a specific object that should contain it. This is the part of the meaning of the Object Oriented Programming paradigm. It's also good to do that when you wish to export or simply pass all these functions to another separate module. And that's about it (:
JavaScript identifiers not to use
I just found out the hard way that naming your variable arguments is a bad idea. var arguments = 5; (function () { console.log(arguments); })(); Output: [] It turns out that arguments is "a local variable available within all functions" so in each new execution context, arguments is shadowed. My question is: Are there any other such treacherous names which, like arguments, are not true reserved words, but will cause still problems?
Yes. Like window or document, for example. See a longer list here ("other javascript keywords"). Wouldn't recommend using any of them, even though some would work as intended. Edit: Like mentioned in javascript.about.com, "While they are not reserved words, the use of those words as variables and functions should be avoided.". They are listing mostly the same things classified as predefined classes and objects and global properties. Example of a problem: var window = 5; (function () { alert(window); })(); the code above has unpredictable results due to fact that window is the word to refer to the window object. Firefox prevents modifications to it, so alert will still refer to window object, whereas in IE8, you'll get alert with value 5.
There are no other automatic symbols inside functions (apart from this, but you cannot create a variable with that name anyway), if that's what you mean. But there are a couple of default global variables, so defining a variable with the same name inside the function will shadow the global variable.
You can get a list of all names used in the global namespace, by executing this in the console: var t = []; for(v in this){t.push(v)} console.log(t.sort()); Result: ["$","ArrayBuffer","Attr","Audio","AudioProcessingEvent","BeforeLoadEvent","Blob","CDATASection","CSSCharsetRule","CSSFontFaceRule","CSSImportRule","CSSMediaRule","CSSPageRule","CSSPrimitiveValue","CSSRule","CSSRuleList","CSSStyleDeclaration","CSSStyleRule","CSSStyleSheet","CSSValue","CSSValueList","CTIsPlayback","CanvasGradient","CanvasPattern","CanvasRenderingContext2D","CharacterData","ClientRect","ClientRectList","Clipboard","CloseEvent","Comment","CompositionEvent","Counter","CustomEvent","DOMException","DOMImplementation","DOMParser","DOMSettableTokenList","DOMStringList","DOMStringMap","DOMTokenList","DataView","DeviceOrientationEvent","Document","DocumentFragment","DocumentType","Element","Entity","EntityReference","ErrorEvent","Event","EventEmitter","EventException","EventSource","File","FileError","FileList","FileReader","Float32Array","Float64Array","FormData","Generator","HTMLAllCollection","HTMLAnchorElement","HTMLAppletElement","HTMLAreaElement","HTMLAudioElement","HTMLBRElement","HTMLBaseElement","HTMLBaseFontElement","HTMLBodyElement","HTMLButtonElement","HTMLCanvasElement","HTMLCollection","HTMLDListElement","HTMLDataListElement","HTMLDirectoryElement","HTMLDivElement","HTMLDocument","HTMLElement","HTMLEmbedElement","HTMLFieldSetElement","HTMLFontElement","HTMLFormElement","HTMLFrameElement","HTMLFrameSetElement","HTMLHRElement","HTMLHeadElement","HTMLHeadingElement","HTMLHtmlElement","HTMLIFrameElement","HTMLImageElement","HTMLInputElement","HTMLKeygenElement","HTMLLIElement","HTMLLabelElement","HTMLLegendElement","HTMLLinkElement","HTMLMapElement","HTMLMarqueeElement","HTMLMediaElement","HTMLMenuElement","HTMLMetaElement","HTMLMeterElement","HTMLModElement","HTMLOListElement","HTMLObjectElement","HTMLOptGroupElement","HTMLOptionElement","HTMLOutputElement","HTMLParagraphElement","HTMLParamElement","HTMLPreElement","HTMLProgressElement","HTMLQuoteElement","HTMLScriptElement","HTMLSelectElement","HTMLSourceElement","HTMLSpanElement","HTMLStyleElement","HTMLTableCaptionElement","HTMLTableCellElement","HTMLTableColElement","HTMLTableElement","HTMLTableRowElement","HTMLTableSectionElement","HTMLTextAreaElement","HTMLTitleElement","HTMLTrackElement","HTMLUListElement","HTMLUnknownElement","HTMLVideoElement","HashChangeEvent","IceCandidate","Image","ImageData","Int16Array","Int32Array","Int8Array","KeyboardEvent","Markdown","MediaController","MediaError","MediaList","MediaStreamEvent","MessageChannel","MessageEvent","MessagePort","MimeType","MimeTypeArray","MouseEvent","MutationEvent","NamedNodeMap","Node","NodeFilter","NodeList","Notation","Notification","OfflineAudioCompletionEvent","Option","OverflowEvent","PERSISTENT","PR","PR_SHOULD_USE_CONTINUATION","PageTransitionEvent","Plugin","PluginArray","PopStateEvent","ProcessingInstruction","ProgressEvent","RGBColor","RTCIceCandidate","RTCSessionDescription","Range","RangeException","Rect","SQLException","SVGAElement","SVGAltGlyphDefElement","SVGAltGlyphElement","SVGAltGlyphItemElement","SVGAngle","SVGAnimateColorElement","SVGAnimateElement","SVGAnimateMotionElement","SVGAnimateTransformElement","SVGAnimatedAngle","SVGAnimatedBoolean","SVGAnimatedEnumeration","SVGAnimatedInteger","SVGAnimatedLength","SVGAnimatedLengthList","SVGAnimatedNumber","SVGAnimatedNumberList","SVGAnimatedPreserveAspectRatio","SVGAnimatedRect","SVGAnimatedString","SVGAnimatedTransformList","SVGCircleElement","SVGClipPathElement","SVGColor","SVGComponentTransferFunctionElement","SVGCursorElement","SVGDefsElement","SVGDescElement","SVGDocument","SVGElement","SVGElementInstance","SVGElementInstanceList","SVGEllipseElement","SVGException","SVGFEBlendElement","SVGFEColorMatrixElement","SVGFEComponentTransferElement","SVGFECompositeElement","SVGFEConvolveMatrixElement","SVGFEDiffuseLightingElement","SVGFEDisplacementMapElement","SVGFEDistantLightElement","SVGFEDropShadowElement","SVGFEFloodElement","SVGFEFuncAElement","SVGFEFuncBElement","SVGFEFuncGElement","SVGFEFuncRElement","SVGFEGaussianBlurElement","SVGFEImageElement","SVGFEMergeElement","SVGFEMergeNodeElement","SVGFEMorphologyElement","SVGFEOffsetElement","SVGFEPointLightElement","SVGFESpecularLightingElement","SVGFESpotLightElement","SVGFETileElement","SVGFETurbulenceElement","SVGFilterElement","SVGFontElement","SVGFontFaceElement","SVGFontFaceFormatElement","SVGFontFaceNameElement","SVGFontFaceSrcElement","SVGFontFaceUriElement","SVGForeignObjectElement","SVGGElement","SVGGlyphElement","SVGGlyphRefElement","SVGGradientElement","SVGHKernElement","SVGImageElement","SVGLength","SVGLengthList","SVGLineElement","SVGLinearGradientElement","SVGMPathElement","SVGMarkerElement","SVGMaskElement","SVGMatrix","SVGMetadataElement","SVGMissingGlyphElement","SVGNumber","SVGNumberList","SVGPaint","SVGPathElement","SVGPathSeg","SVGPathSegArcAbs","SVGPathSegArcRel","SVGPathSegClosePath","SVGPathSegCurvetoCubicAbs","SVGPathSegCurvetoCubicRel","SVGPathSegCurvetoCubicSmoothAbs","SVGPathSegCurvetoCubicSmoothRel","SVGPathSegCurvetoQuadraticAbs","SVGPathSegCurvetoQuadraticRel","SVGPathSegCurvetoQuadraticSmoothAbs","SVGPathSegCurvetoQuadraticSmoothRel","SVGPathSegLinetoAbs","SVGPathSegLinetoHorizontalAbs","SVGPathSegLinetoHorizontalRel","SVGPathSegLinetoRel","SVGPathSegLinetoVerticalAbs","SVGPathSegLinetoVerticalRel","SVGPathSegList","SVGPathSegMovetoAbs","SVGPathSegMovetoRel","SVGPatternElement","SVGPoint","SVGPointList","SVGPolygonElement","SVGPolylineElement","SVGPreserveAspectRatio","SVGRadialGradientElement","SVGRect","SVGRectElement","SVGRenderingIntent","SVGSVGElement","SVGScriptElement","SVGSetElement","SVGStopElement","SVGStringList","SVGStyleElement","SVGSwitchElement","SVGSymbolElement","SVGTRefElement","SVGTSpanElement","SVGTextContentElement","SVGTextElement","SVGTextPathElement","SVGTextPositioningElement","SVGTitleElement","SVGTransform","SVGTransformList","SVGUnitTypes","SVGUseElement","SVGVKernElement","SVGViewElement","SVGViewSpec","SVGZoomAndPan","SVGZoomEvent","Selection","SessionDescription","SharedWorker","SpeechInputEvent","StackExchange","Storage","StorageEvent","StyleSheet","StyleSheetList","TEMPORARY","Text","TextEvent","TextMetrics","TextTrack","TextTrackCue","TextTrackCueList","TextTrackList","TimeRanges","TouchEvent","TrackEvent","UIEvent","URL","Uint16Array","Uint32Array","Uint8Array","Uint8ClampedArray","WebGLActiveInfo","WebGLBuffer","WebGLContextEvent","WebGLFramebuffer","WebGLProgram","WebGLRenderbuffer","WebGLRenderingContext","WebGLShader","WebGLShaderPrecisionFormat","WebGLTexture","WebGLUniformLocation","WebKitAnimationEvent","WebKitBlobBuilder","WebKitCSSFilterValue","WebKitCSSKeyframeRule","WebKitCSSKeyframesRule","WebKitCSSMatrix","WebKitCSSRegionRule","WebKitCSSTransformValue","WebKitIntent","WebKitMediaSource","WebKitMutationObserver","WebKitPoint","WebKitSourceBuffer","WebKitSourceBufferList","WebKitTransitionEvent","WebSocket","WheelEvent","Window","WinterBash","Worker","XMLDocument","XMLHttpRequest","XMLHttpRequestException","XMLHttpRequestProgressEvent","XMLHttpRequestUpload","XMLSerializer","XPathEvaluator","XPathException","XPathResult","XSLTProcessor","__qc","_gaq","_gat","_qevents","addEventListener","alert","apiCallbacks","applicationCache","atob","blur","btoa","captureEvents","careers_adselector","careers_adurl","careers_companycssurl","careers_cssurl","careers_leaderboardcssurl","chrome","clearInterval","clearTimeout","clientInformation","close","closed","confirm","console","crypto","defaultStatus","defaultstatus","devicePixelRatio","dispatchEvent","document","event","external","find","focus","frameElement","frames","gaGlobal","gauth","genuwine","getComputedStyle","getMatchedCSSRules","getSelection","history","i","initFadingHelpText","initTagRenderer","innerHeight","innerWidth","jQuery","jQuery171005593172716908157_1357215797040","jQuery171005593172716908157_1357215797041","length","localStorage","location","locationbar","matchMedia","menubar","moveBy","moveScroller","moveTo","name","navigator","offscreenBuffering","onabort","onbeforeunload","onblur","oncanplay","oncanplaythrough","onchange","onclick","oncontextmenu","ondblclick","ondeviceorientation","ondrag","ondragend","ondragenter","ondragleave","ondragover","ondragstart","ondrop","ondurationchange","onemptied","onended","onerror","onfocus","onhashchange","oninput","oninvalid","onkeydown","onkeypress","onkeyup","onload","onloadeddata","onloadedmetadata","onloadstart","onmessage","onmousedown","onmousemove","onmouseout","onmouseover","onmouseup","onmousewheel","onoffline","ononline","onpagehide","onpageshow","onpause","onplay","onplaying","onpopstate","onprogress","onratechange","onreset","onresize","onscroll","onsearch","onseeked","onseeking","onselect","onstalled","onstorage","onsubmit","onsuspend","ontimeupdate","onunload","onvolumechange","onwaiting","onwebkitanimationend","onwebkitanimationiteration","onwebkitanimationstart","onwebkittransitionend","open","openDatabase","opener","outerHeight","outerWidth","pageXOffset","pageYOffset","parent","performance","personalbar","postMessage","prepareEditor","prettyPrint","prettyPrintOne","print","profileLink","prompt","quantserve","releaseEvents","removeEventListener","resizeBy","resizeTo","sanitizeAndSplitTags","screen","screenLeft","screenTop","screenX","screenY","scriptSrc","scroll","scrollBy","scrollTo","scrollX","scrollY","scrollbars","self","sessionStorage","setInterval","setTimeout","showFadingHelpText","showModalDialog","status","statusbar","stop","styleCode","styleMedia","t","tagRenderer","tagRendererRaw","toolbar","top","uh","v","v8Intl","votesCast","webkitAudioContext","webkitAudioPannerNode","webkitCancelAnimationFrame","webkitCancelRequestAnimationFrame","webkitConvertPointFromNodeToPage","webkitConvertPointFromPageToNode","webkitIDBCursor","webkitIDBDatabase","webkitIDBDatabaseException","webkitIDBFactory","webkitIDBIndex","webkitIDBKeyRange","webkitIDBObjectStore","webkitIDBRequest","webkitIDBTransaction","webkitIndexedDB","webkitIntent","webkitMediaStream","webkitNotifications","webkitPostMessage","webkitRTCPeerConnection","webkitRequestAnimationFrame","webkitRequestFileSystem","webkitResolveLocalFileSystemURL","webkitStorageInfo","webkitURL","window"]; So, these can't / shouldn't be used (at least in Google Chrome), in the global scope. If you declare them as variables in a local scope, you're fine. This won't contain all names used, however, since arguments is only available in the function scope, for example. Note: this function does return all global variables from your libraries, also
JavaScript Closures use global setting object or pass it to each function
another question concerning javascricpt closures. I have a global "settings object". Is it better to use it from within functions in global scope or pass the object every time a function needs to access the object? For a better understanding a little mockup of the situation here Please ignore that "baz()" also gets the passed object within "foobar()" from the global scope within the closure. You see that both versions work fine. The thing is that I am passing whatever object the function needs to work to every function and EVERY time (unneccesary overhead?), which might be nice and easy to read/understand but I am seriously thinking about changing this. Disadvantage would be that I have to keep the "this" scope wherever it gets deeper right? Thanks for your advice!
Your settings object isn't global, it's defined within a closure. As the intent is that it be accessed by other function within the closure, I'd say you were 100% fine to just access that object directly and not pass it as a parameter. FWIW, even if you did pass it as a parameter the overhead is negligible because only a reference to the object is passed, not a copy of the whole object.
So you have basically three options: You want to expose settings as a global variable, and have it accessed by your functions, You want to hide settings as an implementation detail and have it accessed by your functions, You want to give a possibility to supply different settings objects to different functions. Global variable approach Well, I guess it's a little bit like with any global variable. If settings is a singleton (for example it describes your application) and you can't see any benefit in having a possibility to call the same function with different settings objects, then I don't see why it couldn't be a global variable. That said, because of all the naming conflicts, in Javascript it's good to "namespace" all the global variables. So instead of global variables foo and bar you should rather have one global variable MyGlobalNamespace which is an objects having attributes: MyGlobalNamespace.foo and MyGlobalNamespace.bar. Private variable approach Having a private variable accessed by a closure is a good pattern for hiding implementation details. If the settings object is something you don't want to expose as an API, this is probably the right choice. Additional function parameter approach Basically if you see a gain in having a possibility of supplying different settings to different function calls. Or perhaps if you can picture such gain in the future. Obvious choice if you have many instances of settings in your application. EDIT As to the question from the comments: Example 1) var blah = 123; function fizbuzz() { console.log(blah); // <-- This is an example of a closure accessing // a variable console.log(this.blah); // <-- Most likely makes no sense. It might work, // because by default this will be set to a global // object named window, but this is probably not // what you want. In other situations this might // point to another object. } Example 2) var obj = { blah: 123, fizbuzz: function() { console.log(this.blah); // <-- This is *NOT* an example of a closure // accessing a private variable. It's rather the // closest Javascript can get to accessing an // instance variable by a method, though this // terminology shouldn't be used. console.log(blah); // <-- This MAKES NO SENSE, there is no variable blah // accessible from here. } }; In a nutshell, I'd encourage you to read some good book on the fundamental concepts of Javascript. It has its paculiarities and it's good to know them.
Global variables vs. passing a value into a function?
I'm new to JavaScript, and have a simple (I presume) question regarding best practices for accessing variables in functions: When should I declare a global variable, as opposed to simple passing a value into a function?
Declaring a global variable should only be used as an option of last resort. Global variables are bad in general and especially so in javascript. There is simply no way to prevent another piece of javascript from clobbering your global. The clobbering will happen silently and lead to runtime errors. Take the following as an example. // Your code myParam = { prop: 42 }; function operateOnMyParam() { console.log(myParam.prop); } Here i've declared 2 global variables myParam operateOnMyParam This might work fine while testing your javascript in isolation. However what happens if after testing a user combines your javascript library with my javascript library that happens to have the following definitions // My code function myParam() { console.log("..."); } This also defines a global value named myParam which clashes with your myParam. Which one wins depends on the order in which the scripts were imported. But either way one of us is in trouble because one of our global objects is dead.
There are many, many reasons.. but an easy one is.. The argument of a function only exists in the function, while it's running. A global variable exists all the time, which means: it takes up memory until you manually 'destroy' it Every global variable name needs to be unique If, within your function.. you call another function.. which ends up calling the first function, all of a sudden you may get unexpected results. In short: because the function argument only lives for a really short time and does not exist outside the function, it's much easier to understand what's going on, and reduced the risk of bugs greatly.
When dealing with framework-less JavaScript I'll store my simple variables and functions in an object literal as to not clutter up the global namespace. var myObject = { variableA : "Foo", variableB : "Bar", functionA : function(){ //do something //access local variables this.variableA } } //call functions and variables myObject.variableA; myObject.functionA();
Confusing Javascript class declaration
I have some third-party Javascript that has statements like this: FOO = function() { ...functions() ... return { hash } }(); It is working as designed but I'm confused by it. Can anybody define what this structure is doing? Is it just a weird way to create a class?
This is a technique that uses closure. The idiom is well-known, but confusing when you first see it. FOO is defined as the object that the outermost function() returns. Notice the parenthesis at the end, which causes the function to evaluate and return { hash }. The code is equivalent to function bar() { ...functions() ... return { hash } }; FOO = bar(); So FOO is equal to { hash }. The advantage of this is that hash, whatever it is, has access to stuff defined inside the function(). Nobody else has access, so that stuff is essentially private. Google 'Javascript closure' to learn more.
Js doesn't really have classes, per se, but "prototypes". This means that no two objects are ever of the same "type" in the normal type-safe sense, and you can dynamically add members to one instance while leaving the other unmolested. (which is what they have done). Believe it or not, the syntax they have used is probably the most lucid, as it doesn't try to hide behind some C-style class syntax. Doug Crockford's Javascript: The Good Parts is a quick read, and the best introduction to OOP in js that I've come across.
That's not actually a class, just an object. I'd recommend reading this: http://javascript.crockford.com/survey.html Because JavaScript doesn't have block scope, your choice is (mostly) to have all variable reside in global or function scope. The author of your snippet wants to declare some local variables that he doesn't want to be in the global scope, so he declares an anonymous function and executes it immediately, returning the object he was trying to create. That way all the vars will be in the function's scope.
The parans at the end make this the Module Pattern, which is basically a way to have a single instance of an object(Singleton) while also using private variables and functions. Since there's closures hash, if it's itself an object or function, will have access to all variables declared within that anonymous Singleton object.
You're missing an open parens, but it is basically a way of usually hiding information within an object i.e. a way of setting up private and privelaged methods. For example var foo = (function() { /* function declarations */ return { /* expose only those functions you want to expose in a returned object */ } })(); Take a look at Papa Crockford's Private Members in JavaScript. This is basically the pattern you are seeing, but in a slightly different guise. The function declarations are wrapped in a self-invoking anonymous function - an anonymous function that is executed as soon as it's declared. Since the functions inside of it are scoped to the anonymous function, they will be unreachable after the anonymous function has executed unless they are exposed through a closure created by referencing them in the object returned from the execution of the anonymous function. It's generally referred to as the Module Pattern.