This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 9 years ago.
Wondering what the difference between the two code below. In the first case I used this to refer to the object and in the second case I used the object name. Although both works I was wondering whether there is any real difference between the two.
(function() {
var app = {
init: function () {
app.addLun('Hello');
},
addLun: function(a) {
console.log(a);
}
};
});
})();
and
var app = {
init: function () {
this.addLun('Hello');
},
addLun: function(a) {
console.log(a);
}
};
});
})();
this refers to the context/scope of the function, so depending on how you call it, it could refer to app, window, or many other scopes...
app refers to the actual app object if it exists in that scope.
Using this and app are absolutely not the same. Take this (slightly contrived) example:
var app = {
init: {
foo: function () {
// Think 'this' is app?
this.addLun('Hello');
}
},
addLun: function(a) {
console.log(a);
}
};
var app2 = {
init: {
foo: function () {
app2.addLun('Hello');
}
},
addLun: function(a) {
console.log(a);
}
};
app2.init.foo(); // prints Hello
app.init.foo(); // error - no method called addLun
this is the current context, app is the object you have just created.
Yes, there is difference. If you want to have more, that one instance of app object (for example, you can clone it with jQuery.extend()), you need to use second variant for correct work.
Related
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 6 years ago.
Main concern is efficiency.
I am working on javascript scopes and one thing that I am confused about is this inside a function.
I have read many answers and I understand them. But what I am concerned about is efficiency. Have a look at my code.
class Fancy {
constructor () {
}
checkScope (callback) {
console.log('Inside checkScope');
callback ();
}
}
class Prog {
constructor () {
this.name = 'myProg';
this.fancy = new Fancy ();
}
run () {
var that = this;
this.fancy.checkScope(function () {
console.log('Name ', that.name);
});
}
}
var prog = new Prog ();
prog.run();
Now in run() I am storing reference of this in a local variable that. This is working for me. But is it safe? Is it efficient? If no, please suggest me a good strategy/trick.
Thanks :)
Yes it is safe, but you can use the new arrow syntax.It preserve the this.
class Fancy {
constructor () {
}
checkScope (callback) {
console.log('Inside checkScope');
callback ();
}
}
class Prog {
constructor () {
this.name = 'myProg';
this.fancy = new Fancy ();
}
run () {
// Here your don't need var that = this,
// because the arrow function gets the same this
this.fancy.checkScope( () => {
console.log('Name ', this.name);
});
}
}
var prog = new Prog ();
prog.run();
Every simple function has it's this, in your case your
function () {
console.log('Name ', this.name); // this is undefined in 'strict mode'
}
has its own this.So you need to keep the this outside the function and use with alias in the function.In ES6 there is a new arrow syntax function.Arrow functions don't override the this. In your case
run () {
this.fancy.checkScope( () => {
console.log('Name ', this.name);
});
}
the this in the run function and in the parameter function are the same. It means that in the arrow function scope the this refers to that this in which the arrow function was defined.
In the case of efficient, you don't need an extra variable.You don't pollute the local scope with an extra variable. In the performance there is no affect.
This question already has answers here:
var functionName = function() {} vs function functionName() {}
(41 answers)
Closed 7 years ago.
I have been writing functions like
var functionname = function(param)
{
}
rather then
functionname(param)
{
}
does it provide any advantage of the format or any garbage collection happens when i write like the first syntax?
(function() { "use strict"; f(); function f() { console.log(1); }; })();
1
(function() { "use strict"; f(); var f = function() { console.log(1); }; })();
Object expected
Function expressions var name = function() { ... } are not hoisted, while function decarations function name() {...} are.
first of all, u should understand the scope matter for this function.
when u write:
var a = function(){} --> the function is anonymous outside the var a- scope.
it means, that out of this district, the function will not be able to be accessed. another thing is memory usage- here u create a function which takes memory, and a pointer outside the function pointing on it as a soft link.
when u write function a(){} ---> there is a public pointer named a for this function as a hard link.
so, if you want to create a private function- go for it.
i know that it's common to create functions using: function funcName(){);
This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 7 years ago.
Sorry for the title, but it's really hard to put a title on this issue (feel free to suggest a better one).
My issue is best explained via this JsFiddle: http://jsfiddle.net/ryLhcn4q/2/
CS = {};
CS.OverviewController = {
foo: "bar",
render: function() {
console.log("Rendering. foo = " + this.foo);
}
};
CS.handleClick = function(callback) {
console.log("handleClick");
if (callback) {
callback();
}
};
$("button").click(function(e) {
CS.handleClick(CS.OverviewController.render);
});
If you click on the button, the console indicates that the value of foo is undefined. How can I have the correct scope of this, so that the console indicates bar as the value for foo?
You should use
CS.handleClick(CS.OverviewController.render.bind(CS.OverviewController));
.bind defines the context of the function. Or in other words it sets its this object to something.
Your example doesn't work because you refer a function out of its context. The this points to the global scope (i.e. the window object). So:
window.foo = 'global';
$("button").click(function(e) {
CS.handleClick(CS.OverviewController.render);
});
will output global -> jsfiddle
PFB the code, this will work
CS = {};
CS.OverviewController = {
foo: "foo",
render: function() {
console.log("rendering. foo = " + this.foo);
}
};
CS.handleClick = function(e, context, callback) {
console.log("handleClick");
if (callback) {
context[callback]();
}
};
$("button").click(function(e) {
CS.handleClick(e, CS.OverviewController, 'render');
});
JsFiddleUpdated
You can also use "apply" or "call"
This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
Explanation asked about the value of 'this' in Javascript [duplicate]
(2 answers)
Closed 8 years ago.
Simple question. Why do we have set that = this? If we dont, we are in the global scope...but why?
var myObj = {
specialFunction: function () {
},
anotherSpecialFunction: function () {
},
getAsyncData: function (cb) {
cb();
},
render: function () {
var that = this;
this.getAsyncData(function () {
// this now refers to global scope....why?
that.specialFunction();
that.anotherSpecialFunction();
});
}
};
myObj.render();
Writing that = this doesn't change the scope. The way the anonymous function is called will always end up with this being global object,* because that's exactly what the spec says should happen. Using that = this is just a workaround.
You could make this always point to myObj by using Function.call:
var myObj = {
specialFunction: function () {
},
getAsyncData: function (cb) {
cb.apply(this);
},
render: function () {
this.getAsyncData(function () {
this.specialFunction();
});
}
};
and/or using Function.bind:
var myObj = {
specialFunction: function () {
},
getAsyncData: function (cb) {
cb();
},
render: function () {
function callback() {
this.specialFunction();
}
this.getAsyncData(callback.bind(this));
}
};
* Unless you're in strict mode, in which case this is undefined.
take a look at the this keyword in JavaScript and how it works. I’m sure we’ve all come across this issue:
$("myLink").on("click", function() {
console.log(this); //points to myLink (as expected)
$.ajax({
//ajax set up
success: function() {
console.log(this); //points to the global object. Huh?
}
});
});
this is a variable that is automatically set for you when a function is invoked. The value it’s given depends on how a function is invoked. In JavaScript we have a few main ways of invoking functions. I wont talk about them all today, but just the three ways most people use them; either when a function is called as a method, or on it’s own, or as an event handler. Depending on how a function is invoked, this is set differently:
function foo() {
console.log(this); //global object
};
myapp = {};
myapp.foo = function() {
console.log(this); //points to myapp object
}
var link = document.getElementById("myId");
link.addEventListener("click", function() {
console.log(this); //points to link
}, false);
Doing $("myLink").on("click", function() {}) means that when the element is clicked, the function is fired. But this function is bound as an event handler, so this is set to the reference to the DOM element myLink. The success method you define within the Ajax request is just a regular function, and as such when it’s invoked, this is set to the global object, as it is when any function that’s not an event handler or an object method is.
$("myLink").on("click", function() {
console.log(this); //points to myLink (as expected)
var _this = this; //store reference
$.ajax({
//ajax set up
success: function() {
console.log(this); //points to the global object. Huh?
console.log(_this); //better!
}
});
});
Source: http://tinyurl.com/melbl92
EDIT: in JavaScript the "this" context depends on how your function is called, example:
function helloWorld()
{
console.log(this);
}
And here two ways to call this function:
new helloWorld(); note that if you call your function in this
way, the context of this will be the context of the function +
prototype, so your console will show this: helloWorld {}
helloWorld(); if you call your function without of the "new",
the context of "this" will be global(Window), so your console will show
this: Window about:home
Ok, with this little explanation i will try to explain now why you
have sometimes to use self/that...
Imagine that you want to use this.name inside this.hello function. Like I said before, the context of "this" depends on how your function is called, so if you want to ensure that this.name inside of this.hello function refer to this.name outside is recommended that you use self/that to avoid what happens bellow
function helloWorld(){
var self = this;//or that = this
this.name = "YourName"
this.hello = function(){
console.log(this); //the context of "this" here will be: "hello {}"
return this.name; //undefined, because you don't have name attribute inside hello function
}
new this.hello(); //note how hello is called here...
}
var test = new helloWorld();
And here a good explanation about context x scope:
http://ryanmorr.com/understanding-scope-and-context-in-javascript/
This question already has answers here:
Self-references in object literals / initializers
(30 answers)
Closed 9 years ago.
Sometime ago I heard that it was good practice to wrap your code in a big object to serve as a namespace in order to reduce global namespace cluttering and to facilitate library export, so I tried this.
var wrapper = {
foo: function(){
return 42;
},
bar: this.foo()
};
It fails, claiming that "foo is not defined".
Calling methods before finishing the object declaration is probably bad, so I moved bar, and it worked.
var wrapper = {
foo: function(){
return 42;
},
};
wrapper.bar = wrapper.foo();
I feel that this can become kind of ugly, especially with nested namespaces and such, so are there any workarounds that don't make it hard to see all of the wrapper's members at once?
The problem is that this is going to equal the global context. You need to access the function like so:
var wrapper = {
foo: function(){
return 42;
},
bar: null,
init : function() {
// all initialization code goes here
wrapper.bar = wrapper.foo();
}
};
wrapper.init();
This method is great for organizing your code into logical chunks so you and future developers can easily find what you are looking for in your javascript.
var wrapper = {
foo: (function(){
return 42;
})()
};
alert(wrapper.foo);
http://jsfiddle.net/ee8Ww/
Using this like that will not work unless wrapper is 1) a function, and 2) you instantiate it to use it:
var wrapper = function() {
this.foo = function() { return 42; }
this.bar = this.foo();
};
var wrapperInstance = new wrapper();
alert(wrapperInstance.bar()); // 42
wrapperInstance.foo(); // also works