JavaScript function members differences - javascript

I'm still confused about this part of the closure although I read about it a lot (also here in the site).
Took the code from here:
http://www.crockford.com/javascript/private.html
So what is the different between this:
function Container(param) {
this.member = param;
}
...And this -
function Container(param) {
var member = param;
// and also in case it's without "var", I.e. global
}
Please explain what happens when you're creating the obj for each case -
var myContainer = new Container('abc');
Also -
What are the access differences for the parameter from the object? And can you give example for a function as a parameter and a returning function?
Thanks a lot!

Here is my opinion:
When you use the new to create an object through function,the variable initial by var is local variable:
function Test(){
var name = "John";
this.getName = function(){
return name;
}
}
var obj1 = new Test();
console.log(obj1.name); //undefined
console.log(obj1.getName()); //John
That means you can't read the variable directly outside the function.This is like private variable in Java or c++;
but when you use this.name = "John", this is a different situation:
function Test2(){
this.name = "John";
}
var obj2 = new Test2();
console.log(obj2.name) //"John"
you can read the variable directly, this is like "public" variable in java or c++.
Hope this can work for you. : )

In function Test, when we declare a variable obj1 with new Test. It have been created through the contructor function which is called "Test".
This process is like we call a function in a normal way. Of course that make a local variable "name". When we decleared a function expression which is called "this.getName", that just mean an expression to function "Test".
But when we call the "new Test".It return a object which have a key-value call "getName:function{}". When we call "obj1.getName", it return the variable "name". But it cannot find the getName's local variable "name", so it will search its parent's scope to find if there is a variable "name",it will not stop until we get it or just return "undefined". That make an "quote" to keep the variable "name" in memory, but we just can get it through the function "getName".
For all of this, we make a private variable in our function "Test". : ) Hope this can help.

Related

compare Javascript scope

The following segment:
var obj = {
name:'Tom',
sayHello:function() {
console.log("hello," + this.name);
}
}
var name = 'Kevin';
var method = obj.sayHello;
method();
will get the output:
hello,undefined
but, if change var name = 'Kevin'; to name = 'Kevin'; The output will be hello,Kevin. Why they are different?
There are two halves to the answer:
When you use var method = obj.sayHello;, you are decoupling the function from obj. When you invoke the a method without giving it an explicit object, (ie, method() instead of obj.sayHello()), JavaScript sets this to the global object, window.
When you define a variable using var name = 'Kevin', you're creating a local variable with function scope. When you define a variable using name = 'Kevin', you're creating a global variable, attached to the global object, window. This is identical to writing window.name = 'Kevin'.
These two things combine to mean that, inside sayHello, this is window and this.name is Kevin.
To solve this, you need to use bind, which returns a copy of your method with its context fixed to the object provided as an argument to bind:
var method = obj.sayHello;
new_method = method.bind(obj);
new_method(); // hello, Tom
sayHello:function() {
console.log("hello," + this.name);
}
this in this function refers to the global object. When you change var name = 'Kevin'; to name = 'Kevin';, name variable is set in the global object. Since, name is set in global and this is global, this.name refers to Kevin and it prints hello,Kevin.
The this keyword can be tricky to get.
If you call obj.sayHello, the this keyword will refer to obj.
When you write method = obj.sayHello that the same thing that writing:
window.method = function() { console.log("hello," + this.name); }
The this keyword will now refer to window.
That's why when you reference a variable having name for its name, you write window.name which can be found by your function.
How you call a function determines the value of this in the method. In your way of calling:
var method = obj.sayHello;
method();
You are losing the obj reference to this inside of your invocation of sayHello() so this is set to the global object or undefined, not set to obj. Thus, the errors you are getting.
When you do this:
var method = obj.sayHello;
All, it does it put a reference to the sayHello function in the method variable. Nowhere is anything to do with obj stored in method. So, when you then call method(), there is no object reference at all so instead of obj.sayHello() which causes this to be set to obj, you're just calling sayHello() all by itself which does not set the value of this to obj.
There are multiple ways to fix it.
1) Helper Function.
var method = function() {obj.sayHello()};
method();
2) Use .bind()
Here .bind() will create a helper function for you.
var method = obj.sayHello.bind(obj);
method();
3) Change sayHello() method
You can change the sayHello() method so it doesn't use the this pointer (which works fine if it is a singleton object, but not if there are multiple instances):
sayHello:function() {
console.log("hello," + obj.name);
}

Understanding JavaScript function declaration syntax [duplicate]

This question already has answers here:
var functionName = function() {} vs function functionName() {}
(41 answers)
Closed 9 years ago.
After using JavaScript for a while, I came up with some questions.
The way to declare a function is:
var myFunction = function(param){//code here}
But there is also another way to declare a function which is
function myFunction(param){//some code}
What's the difference between the two methods to declare a function?
My second question is, I've understood that you can create an object from a function that's declared as:
function Person(name){this.name=name;}
And then, you can have another function declared like this:
function Speak(){console.log(this.name);}
How does the function Speak knows that it's related to the Person Object?
The first one is expression
var myFunction = function(param){//code here}
Second is declaration
function myFunction(param){//some code}
see this article
http://kangax.github.io/nfe/
When u use the word var, your'e declaring a variable realtive to where it's defined, and cannot be accesed from out wheres, and if its inside a function, it's destroyed at the end of the execution, and if you dont use it, you're defining on global ambit, and the variable still exists after the function execution.
The second thing is for programming OOP
Yo can use functions as same as it they were pure objects:
var person = {
name: null,
setName: function (name) {
this.name = name
}
}
Then you can access it's property
person.setName('john');
console.log(person.name);
in the shape of a function
function Person(name){
this.name = null;
}
var john = new Person('John');
console.log(john.name);
When you use this syntax:
function f1(){}
then f1 can be used everywhere in the current scope:
// we can call f1 even before definition of the function
f1(); // it works
function f1(){}
But, When we use this syntax:
var f1 = function(){};
then f1 is like as a pointer to an anonymous function which can be used after the point of assignment:
// we can't call it before assignment of our var
//f1(); // f1 is undefined here!
var f1 = function(){}
// we can call it here
f1(); // works
The second syntax is make more sense when you consider that every function is also an object. for example, we can have a function be a property of an object, like this:
var myObject = new Object();
myObject.say = function(x) {alert(x);};
// myObject now has a property/method named "say"
myObject.say("Hello");
About the second question: the this keyword. can you give the (outer) scope of your code which defines your Person and Speak functions? the code you wrote won't work as it is written. If you want to set proper reference for this in Speak function, you have to write something such as below:
function Person(name){ this.name=name; }
function Speak(){ alert(this.name); }
Person.prototype.DoSpeak = Speak; //here we attach DoSpeak to Speak function
var p = new Person("Saeed");
p.DoSpeak(); //this will work
Both are declaration
1) var myFunction = function(param){//code here}
This is a declaration that is assigned to 'myFunction' local variable
You can set an identifier for that function for debug or recursion purposes
var myFunction = function myFunctionIdentifier(param){ console.log(myFunctionIdentifier.toString())}
But to call this function you have to use 'myFunction ' variable
Another way to perform nested call is by using the arguments.callee that points to the function itself
var myFunction = function(param){ console.log(arguments.callee.toString())}
2) function myFunction(param){//some code}
This is a declaration that is assigned to the scope variable
in case you are in the global area it will be assign (for example in the browser) to the window object
So in fact window["myFunction"]() is valid
* About this question...
function Person(name){this.name=name;}
function Speak(){console.log(this.name);}
The reason that Speak 'knows' Person name is all about JavaScript scope.
Since both using the same scope, both functions 'speak' with the same this.
For example: if you code both functions in the global scope, this == window object thus
console.log(window['name']); will give you the name.
You don't want to code in that way .. since another function using this.name will override you existing logic.
If you will instantiate the Person entity
var person = new Person();
Then person variable will be this, this == person object
And the you can assign Speak in two or more ways:
inline:
function Person() {
...
this.Speak = function ...
}
outside the code, since person assign to (Person)this
person.Speak = function() ...
or the best way, use the prototype object:
Person.prototype.Speak = function() ...

Why do I have to use "this" to access in inner property of a function

What is the difference between
function person(first_name, last_name) {
this.first = first_name
this.last = last_name
}
and this:
function person(first_name, last_name) {
var first = first_name
var last = last_name
}
Why only the first one makes person.first & person.last accessible outside the function?
The this keyword within a function is called the invocation context.
1) If you define your function as a member of an object (a method):
myObject.someMethod = function() { this.x = 2; };
then the invocation context, this, is the object to which the method is being added, myObject. So after calling myObject.someMethod(); above, myObject.x is then 2. The member x is undefined until you call the method, unless you defined it before.
2) If you use your function as a constructor with the new keyword, then this refers to the new object that is being created:
function MyX() { this.x = 3; };
var myX = new MyX();
You'll then have property myX.x set to 3.
Note that I called my constructor MyX(), not myX(). You should call yours Person(), not person(). It's just a convention, but it is useful to indicate that a function is meant to be used as a constructor.
3) Finally, if you use this within a function that you call as neither a method nor a constructor, then this refers to the global object (document or, equivalently, window). Note however that if you are using javascript in strict mode (which you should do), this is undefined in such a situation, which means that you basically cannot use this in a function that is not a method or a constructor.
Your specific question refers to case 2), the constructor. this.x = 3 in the constructor just sets property x of the newly created object. After some object myX is created, you can then access and modify x externally as any other object property using myX.x.
when you write constructor function ( using new) - you add properties using this.XXX
then you do :
var p = new Person('s','d');
and then you have access to p.first etc.
in the second example :
youre not creating any properties..
youre only creating private variables.
so you cant access them...
By using this.something you're saying that THIS is an object and something is his property.
By using var, you're saying that it's just a variable and not a property.
More information about variable vs property:
http://javascriptweblog.wordpress.com/2010/08/09/variables-vs-properties-in-javascript/
Because of function scope.
A variable lifetime is between the curly braces of the function. The this keyword allows to access the function properties outside of it.
Definitely take a look at this link: https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope
'var' keyword make a variable scoped. In the last example var first and var last create variable accessible only in the scope of the function. You can see this as a local variable in a constructor.
when in javascript you declare a variable as
var variable
it only exists inside the method where you declared it. If you want a variable to be accessible for everyone (that is, global) it has to be declared without the 'var' part
You do not necessarily have to use this. It'd also work fine if you've got a structure like this:
Person = function(first_name, last_name) {
var first, last;
create(first_name, last_name);
function create(first_name, last_name) {
first = first_name
last = last_name
}
return {
firstName: first,
lastName: last
}
}

What is the difference between declaring javascript objects with var vs. with function?

I'm a confused newbie. I read in a tutorial that you create a javascript object like so:
function myObject() {
this.myProperty = "a string";
this.myMethod = function () {
//Method code
}
}
Then I read somewhere else that you create an object like so:
var myObject = {
myProperty: "a string",
myMethod : function () {
//Method code
}
}
What is the (non-subjective) difference between the two? Is there an official right way and a wrong way?
Both declarations are correct but they have different semantics.
The first type of declaration allows you to create instances of your objects:
var t = new myObject();
// then use t
t.myProperty = "some value";
var otherT = new myObject();
otherT.myProperty = "some other value";
The second is almost like a static object:
myObject.myProperty = "some value";
Here is a direct comparison...
function myObject() {
This declares the function when JavaScript is parsed...
var myObject = function () {
This declares the function at run time.
If you use the "var" method, your function must be declared before you use it... try this example.
myFunction(); // Works
myVarFunction(); // Boom
var myVarFunction = function () { alert("Hi"); };
function myFunction() { alert("Hi"); };
So why use the "var" method if you have to be more careful to use it? It is all to do with the scope... scoped functions are considered better.
UPDATE: And there are some great explanations here:
var functionName = function() {} vs function functionName() {}
The major difference between the two is that one variable is local and the other is global. “var” basically defines the scope of the variable.
When we add var to a variable value assignment, javascript ensures that the variable is confined to whichever function it is assigned to and does not collide with the same name variable within another function.
When we don’t use var, then it is declared as a global function and chances of collision can happen. So it’s always advisable to use “var” before variable value assignment. If needed use an anonymous function for closure.

How to get class object's name as a string in Javascript?

Let's say I instantiate an object in Javascript like this:
var myObj = new someObject();
Now, is it possible to obtain the var object's name as string 'myObj' from within one of the class methods?
Additional details (edited):
The reason why I would like to get the name of the variable holding reference to the object is that my new myObj would create a new clickable DIV on the page that would need to call a function myObj.someFunction(). As I insert the new DIV I need to know the name of the variable holding reference to the object. Is there maybe a better way of doing this?
You are right, sorry for the mixup in terminology.
The reason why I would like to get the name of the variable holding reference to the object is that my new myObj would create a new clickable DIV on the page that would need to call a function myObj.someFunction(). As I insert the new DIV I need to know the name of the variable holding reference to the object. Is there maybe a better way of doing this?
Shog9 is right that this doesn't make all that much sense to ask, since an object could be referred to by multiple variables. If you don't really care about that, and all you want is to find the name of one of the global variables that refers to that object, you could do the following hack:
function myClass() {
this.myName = function () {
// search through the global object for a name that resolves to this object
for (var name in this.global)
if (this.global[name] == this)
return name
}
}
// store the global object, which can be referred to as this at the top level, in a
// property on our prototype, so we can refer to it in our object's methods
myClass.prototype.global = this
// create a global variable referring to an object
var myVar = new myClass()
myVar.myName() // returns "myVar"
Note that this is an ugly hack, and should not be used in production code. If there is more than one variable referring to an object, you can't tell which one you'll get. It will only search the global variables, so it won't work if a variable is local to a function. In general, if you need to name something, you should pass the name in to the constructor when you create it.
edit: To respond to your clarification, if you need to be able to refer to something from an event handler, you shouldn't be referring to it by name, but instead add a function that refers to the object directly. Here's a quick example that I whipped up that shows something similar, I think, to what you're trying to do:
function myConstructor () {
this.count = 0
this.clickme = function () {
this.count += 1
alert(this.count)
}
var newDiv = document.createElement("div")
var contents = document.createTextNode("Click me!")
// This is the crucial part. We don't construct an onclick handler by creating a
// string, but instead we pass in a function that does what we want. In order to
// refer to the object, we can't use this directly (since that will refer to the
// div when running event handler), but we create an anonymous function with an
// argument and pass this in as that argument.
newDiv.onclick = (function (obj) {
return function () {
obj.clickme()
}
})(this)
newDiv.appendChild(contents)
document.getElementById("frobnozzle").appendChild(newDiv)
}
window.onload = function () {
var myVar = new myConstructor()
}
Short answer: No. myObj isn't the name of the object, it's the name of a variable holding a reference to the object - you could have any number of other variables holding a reference to the same object.
Now, if it's your program, then you make the rules: if you want to say that any given object will only be referenced by one variable, ever, and diligently enforce that in your code, then just set a property on the object with the name of the variable.
That said, i doubt what you're asking for is actually what you really want. Maybe describe your problem in a bit more detail...?
Pedantry: JavaScript doesn't have classes. someObject is a constructor function. Given a reference to an object, you can obtain a reference to the function that created it using the constructor property.
In response to the additional details you've provided:
The answer you're looking for can be found here: JavaScript Callback Scope (and in response to numerous other questions on SO - it's a common point of confusion for those new to JS). You just need to wrap the call to the object member in a closure that preserves access to the context object.
You can do it converting by the constructor to a string using .toString() :
function getObjectClass(obj){
if (typeof obj != "object" || obj === null) return false;
else return /(\w+)\(/.exec(obj.constructor.toString())[1];}
You might be able to achieve your goal by using it in a function, and then examining the function's source with toString():
var whatsMyName;
// Just do something with the whatsMyName variable, no matter what
function func() {var v = whatsMyName;}
// Now that we're using whatsMyName in a function, we could get the source code of the function as a string:
var source = func.toString();
// Then extract the variable name from the function source:
var result = /var v = (.[^;]*)/.exec(source);
alert(result[1]); // Should alert 'whatsMyName';
If you don't want to use a function constructor like in Brian's answer you can use Object.create() instead:-
var myVar = {
count: 0
}
myVar.init = function(n) {
this.count = n
this.newDiv()
}
myVar.newDiv = function() {
var newDiv = document.createElement("div")
var contents = document.createTextNode("Click me!")
var func = myVar.func(this)
newDiv.addEventListener ?
newDiv.addEventListener('click', func, false) :
newDiv.attachEvent('onclick', func)
newDiv.appendChild(contents)
document.getElementsByTagName("body")[0].appendChild(newDiv)
}
myVar.func = function (thys) {
return function() {
thys.clickme()
}
}
myVar.clickme = function () {
this.count += 1
alert(this.count)
}
myVar.init(2)
var myVar1 = Object.create(myVar)
myVar1.init(55)
var myVar2 = Object.create(myVar)
myVar2.init(150)
// etc
Strangely, I couldn't get the above to work using newDiv.onClick, but it works with newDiv.addEventListener / newDiv.attachEvent.
Since Object.create is newish, include the following code from Douglas Crockford for older browsers, including IE8.
if (typeof Object.create !== 'function') {
Object.create = function (o) {
function F() {}
F.prototype = o
return new F()
}
}
As a more elementary situation it would be nice IF this had a property that could reference it's referring variable (heads or tails) but unfortunately it only references the instantiation of the new coinSide object.
javascript: /* it would be nice but ... a solution NOT! */
function coinSide(){this.ref=this};
/* can .ref be set so as to identify it's referring variable? (heads or tails) */
heads = new coinSide();
tails = new coinSide();
toss = Math.random()<0.5 ? heads : tails;
alert(toss.ref);
alert(["FF's Gecko engine shows:\n\ntoss.toSource() is ", toss.toSource()])
which always displays
[object Object]
and Firefox's Gecko engine shows:
toss.toSource() is ,#1={ref:#1#}
Of course, in this example, to resolve #1, and hence toss, it's simple enough to test toss==heads and toss==tails. This question, which is really asking if javascript has a call-by-name mechanism, motivates consideration of the counterpart, is there a call-by-value mechanism to determine the ACTUAL value of a variable? The example demonstrates that the "values" of both heads and tails are identical, yet alert(heads==tails) is false.
The self-reference can be coerced as follows:
(avoiding the object space hunt and possible ambiguities as noted in the How to get class object's name as a string in Javascript? solution)
javascript:
function assign(n,v){ eval( n +"="+ v ); eval( n +".ref='"+ n +"'" ) }
function coinSide(){};
assign("heads", "new coinSide()");
assign("tails", "new coinSide()");
toss = Math.random()<0.5 ? heads : tails;
alert(toss.ref);
to display heads or tails.
It is perhaps an anathema to the essence of Javascript's language design, as an interpreted prototyping functional language, to have such capabilities as primitives.
A final consideration:
javascript:
item=new Object(); refName="item"; deferAgain="refName";
alert([deferAgain,eval(deferAgain),eval(eval(deferAgain))].join('\n'));
so, as stipulated ...
javascript:
function bindDIV(objName){
return eval( objName +'=new someObject("'+objName+'")' )
};
function someObject(objName){
this.div="\n<DIV onclick='window.opener."+ /* window.opener - hiccup!! */
objName+
".someFunction()'>clickable DIV</DIV>\n";
this.someFunction=function(){alert(['my variable object name is ',objName])}
};
with(window.open('','test').document){ /* see above hiccup */
write('<html>'+
bindDIV('DIVobj1').div+
bindDIV('DIV2').div+
(alias=bindDIV('multiply')).div+
'an aliased DIV clone'+multiply.div+
'</html>');
close();
};
void (0);
Is there a better way ... ?
"better" as in easier? Easier to program? Easier to understand? Easier as in faster execution? Or is it as in "... and now for something completely different"?
Immediately after the object is instantiatd, you can attach a property, say name, to the object and assign the string value you expect to it:
var myObj = new someClass();
myObj.name="myObj";
document.write(myObj.name);
Alternatively, the assignment can be made inside the codes of the class, i.e.
var someClass = function(P)
{ this.name=P;
// rest of the class definition...
};
var myObj = new someClass("myObj");
document.write(myObj.name);
Some time ago, I used this.
Perhaps you could try:
+function(){
var my_var = function get_this_name(){
alert("I " + this.init());
};
my_var.prototype.init = function(){
return my_var.name;
}
new my_var();
}();
Pop an Alert: "I get_this_name".
This is pretty old, but I ran across this question via Google, so perhaps this solution might be useful to others.
function GetObjectName(myObject){
var objectName=JSON.stringify(myObject).match(/"(.*?)"/)[1];
return objectName;
}
It just uses the browser's JSON parser and regex without cluttering up the DOM or your object too much.

Categories

Resources