Something I don't understand about 'use strict' and this - javascript

As far as I know, everything you declare in JavaScript, belongs to the global object (unless you declare something inside of an object, then the object would belong to the window object, and whatever you declare inside of it, to the object), so, inside of a browser environment, the global object is window.
Say you declare:
var x = 'hi'
This could be accessed with:
x
OR
window.x
And both are absolutely the same, right? So why, with 'use strict', when returning this from a 'global' variable, can I only get the window object if I specify that said function belongs to window?
function fun() {
'use strict';
return this;
}
fun(); // undefined
window.fun(); // window object
// Aren't both absolutely the same?
Also, why does this function return undefined, if the function is supposed to belong to obj?
obj = {
method: function () {
'use strict';
function yeah() { // Doesn't this belong to obj?
return this; // It certainly doesn't seem that 'yeah'
} // belongs to window.
return yeah();
}
};
Thanks.

So why, with 'use strict', when returning this from a 'global' variable, can I only get the window object if I specify that said function belongs to window?
You can get the window object by simply accessing it as window.
It won't be the value of this because that feature made it easy to accidentally write insecure code and came with a performance cost.
From MDN:
Not only is automatic boxing a performance cost, but exposing the
global object in browsers is a security hazard, because the global
object provides access to functionality that "secure" JavaScript
environments must restrict. Thus for a strict mode function, the
specified this is not boxed into an object, and if unspecified, this
will be undefined
Also, why does this function return undefined, if the function is supposed to belong to obj?
While yeah is in the scope of a function that is a method of obj, yeah itself isn't a method of obj as you aren't calling it as one.
i.e. because you are calling yeah() and not obj.yeah() (or yeah.call(obg) etc).
That has nothing to do with "use strict" though.

this inside of a function is supposed to return the object that the function was invoked on (using the obj.method() syntax).
Without use strict the value of this will be set to window if the function is called any other way (for example by just doing func() instead of obj.func()). That is quite confusing. use strict makes sure that this is properly undefined when the function is not called as an object method.

Related

Javascript hide the context

What's the best way for a method to call another method and pass the arguments in not-by-reference fashion?
i.e.
function main() {
let context = {};
// Pass context to someOtherFunction
// Such that console.log(context) in this function does not show `{whatever: true}`
}
function someOtherFunc(context) {
context.whatever = true;
}
I realize I can clone the context and pass that. But I was wondering if there was another way to do this, maybe using anonymous function wrap?
Okay, let's break this down a bit
const context = {x: true};
Above, you create an object (named context) in the global scope.
function(x) {
"use strict";
x.y = true;
}
You create an anonymous function that takes a reference to an object, and adds a new property y to that object
(/*...*/)(context);
You wrapped the above function into an IIFE so it immediately executes. For the parameter, you supplied a reference to the global context object, which is referenced by x inside the IIFE.
Objects are passed around by reference. Passing context in to the function doesn't create a new object x that is a copy of the context, it creates a new reference x that references the same object that context references.
If you need to actually copy the provided object into a new object, you need to do that yourself. As mentioned above, one mechanism is to stringify the object into JSON and then parse the JSON back to a new object. There are others depending on what you need to accomplish.
This isn't even a scope or context question at all - it's passing a reference to an object in to a function. Even if your IIFE had no way whatsoever of directly accessing the context variable, once you pass a reference to that object as an input to the function, the function has the reference and can do what it likes to it.
You also seem to misunderstand about how IIFEs hide data. You hide things inside the IIFE from things outside, not vice versa. Even then, it won't prevent you from passing a reference outside of the IIFE. Here's an example:
function changeName(animal) {
"use strict"
//myDog.name = "Rex"; // Error - myDog isn't a valid reference in this scope
//myCat.name = "Rex"; // Error - myCat isn't a valid reference in this scope either
animal.name = "Rex"; // Perfectly legal
}
(function () {
var myDog = {name: "Rover"};
var myCat = {name: "Kitty"};
console.log(myDog);
console.log(myCat);
changeName(myDog); // Even though changeName couldn't directly access myDog, if we give it a reference, it can do what it likes with it.
console.log(myDog);
})()
In this case, changeName has no access to myDog or myCat which are purely contained within the closure formed by the IIFE. However, the code that exists within that IIFE is able to pass a reference to myDog to changeName and allow it to change the name of the dog, even though changeName still couldn't access the object using the myDog variable.
This is because you are not technically redefining x, but adding properties to it.
I didn't really understood where your doubts came from so this is (to the best of my knowledge) an explanation of what your code is doing.
I'll try to translate the code to human-english.
Define the variable context in the "global scope". (It can be read from anywhere)
It cannot be redefined because its a constant.
Afterwards, define an anonymous self-invoking function (which "starts" a new "local scope" above the global scope so it has access to everything the global scope had access to)
This self invoking function grabs parameter x and adds the property y with a value of true to x and calls itself with the variable context
Read the value of context.
Please read:
JavaScript Scope
JavaScript Function Definitions (Self-Invoking Functions)

"this" as scope limiter?

I'm trying to understand "this" and everything I've looked at talks about context. What this has led me to is the idea that "this" is a scope limiter. It makes sure your variables are referenced using the proper scope, mostly by keeping variables "local" -ish in scope, and keeping them from reaching too far out from where the running code is.
My question is: is that correct? I tried to do searches using the concept I'm trying to get across, but those came up with totally bad results. There is a lot of nuance with "this", and from the reading I've done, I feel like this is a better explanation than what I've seen, but I want to make sure I'm correct in that thinking.
this and variable scope are separate concepts. Variable scope refers to which variables can be accessed from where within your application. Just because you wrote var foo somewhere doesn't mean that you can access it from everywhere throughout your codebase. In Javascript each function introduces a new scope, and scopes nest in a way that inner functions have access to the scope of outer functions, but not vice versa.
this on the other hand is simply a "magic" reference to the "current" object. Maybe it's helpful to explain this idea in the context of other, classical languages first:
class Foo {
protected $bar;
public function baz() {
echo $this->bar;
}
}
In PHP the magic keyword $this refers to the current object instance. Each time you call new Foo, a new instance of this class is created. Every time you call $foo->baz(), the same function is executed, though with $this set to the appropriate object instance so each object instance can access its own data.
In Python this is actually a lot more explicit:
class Foo:
def baz(self):
print self.bar
Python does not have a magic keyword to refer to the current object instance. Instead, every method call on an object gets the current object passed explicitly as its first argument. This is typically named self. If Python seems too alien to you, the above in PHP syntax would be:
class Foo {
public function baz($this) {
echo $this->bar;
}
}
Technically the functions in those classes do not really "belong" to any "class". They're just functions. You just need some way for those functions to be able to refer to a polymorphic object in order for them to be instance methods. Take for example:
function baz($obj) {
echo $obj->baz;
}
That's essentially exactly the same as what the class method does above, with the difference being that $obj is explicitly injected instead of $this being magically "there".
Javascript has the same thing, except that this is available in every function (not just "class" functions) and that the object this points to can be freely changed at runtime. this is simply a magic keyword that points to an object, period.
function Foo() {
this.bar = null;
this.baz = function () {
console.log(this.bar);
}
}
When calling regular functions on objects like foo.baz(), this typically refers to foo inside of baz(); though it really doesn't have to:
foo.baz.apply(someOtherObj);
This takes the function foo.baz and calls it while setting the this keyword inside baz to someOtherObj. It freely re-associates the function with another object instance, if you will. But only because the only thing that "bound" the function to the object in the first place was the this keyword anyway. The function will still simply do console.log(this.bar), whatever this.bar refers to.
A more complete example:
function Foo() {
this.bar = 'baz';
}
Foo.prototype.speak = function () {
alert(this.bar);
};
var o = new Foo();
o.speak(); // alerts 'baz'
alert(o.bar); // also alerts 'baz'
var o2 = { bar : 42 };
o.speak.apply(o2); // alerts 42
As you can see, this doesn't limit the scope of anything. What's happening here?
The Foo constructor is called with new Foo(). new simply creates a new object and executes Foo() with this set to this new object. Basically:
var tmp = {}; // tmp does not *actually* exist,
// that's more or less what `new` does behind the scenes
Foo.apply(tmp);
The Foo constructor assigns the bar property of that new object.
tmp.bar = 'baz';
The new object is assigned to o.
var o = tmp;
o.speak() is a function bound to that object through its prototype. Calling it as o.speak(), this inside speak() refers to the o object. Because that object has a property bar, this works.
Notice that it's also possible to do alert(o.bar). The .bar property was set on this originally, then this became o. So o has the property .bar, which is a regular property of the object. It's not scope limited or anything.
Next, we simply create another object o2, which also happens to have a bar property. Then we call o.speak, but we explicitly override the choice of what this refers to using apply. We simply do a switcheroo on what object the this keyword refers to. Thereby the speak function alerts the bar property of the o2 object.
As you see (hopefully, I know this can be brain bending at first), this is nothing more and nothing less than a reference to an object. That's all. It doesn't limit at all the scope of anything. functions limit scopes, this is just an arbitrary object. Anything you set on this is not limited in scope; on the contrary, it's always publicly accessible from anywhere you have access to the object.
It's incredible how trivial it all is once you manage to wrap your head around it. this refers to an object, it is simply Javascript's magic keyword to refer to an object. There are certain trivial rules which object it refers to at any given time, but all those can be bend and broken and reassigned. An object is simply a thing with properties. The properties can be functions. Only functions limit variable scope. That's pretty much all there is to it. Don't try to interpret anything else into this.

Why does this refer to window or object based on where parenthesis are placed? And return undefined

I am working on flexible javascript widget. In the course of some testing, I noticed that the context of this changes based on whether the parenthesis used to call a function are placed inside an object or in the global context of its call. Why do the parenthesis matter? And why would parenthesis inside the object refer to window and when placed in global context refer to the object. It seems like it would be the other way around.
Also undefined is returned in both instances. Is there a way to execute the function without returning anything?
I feel like I'm missing something important about this and don't want to miss out.
//this refers to window
var dataSource = {
read: read()
};
function read(){
console.log(this);
}
dataSource.read;
//this refers to dataSource object
var dataSource = {
read: read
};
function read(){
console.log(this);
}
dataSource.read();
Your code is doing two different things.
The first example is executing read() as the object definition is executed (read() is available because it's a function declaration and is hoisted, though this isn't related to the problem you're experiencing). It is called without any context so its this is window (as per the specification, where window is the browser's global object).
The second example has a reference to read(), which is then executed at the end of the block. Because it's executed as a property of dataSource, its this will become that. However, if you first assigned that reference to somewhere else and then invoked it via that reference, you'd again lose that this context.
For fine-grained control of this, take a look at bind(), call() and apply().
Also undefined is returned in both instances. Is there a way to execute the function without returning anything?
A function always has a return value (undefined if not explicitly set), but you're free to ignore it.
The scoping of this can be a tricky topic in javascript. That said, I can expand my answer on the general rules regarding the scope of this if need be.
But to answer your specific question, whenever you reference this inside an object literal, it by default, refers to the object literal itself.
Edit: as long as the function was invoked as a property of the object literal.
Where as, almost in any other situation I can call to mind, this will refer to the window object unless specified when invoking said function using apply() or call().
When this is used outside of objects it refers to the global object which in browser environment is window. Otherwise it refers to the last bareword before the last dot in the invocation.
For example:
function foo () {return this};
var bin = {bar:{foo:foo},foo:foo};
foo(); // returns window
bin.foo(); // returns bin
bin.bar.foo(); // returns bar
// ^
// |
// '------ last bareword before the last dot in the invocation
Now, as to why the location of the parenthesis matter. I think you should be able to guess by now:
When we add a parenthesis to a word (variable/name/reference) what we're doing is make a function call:
foo(); // call foo
If we don't add the parenthesis, what we're doing is refer to the object:
foo; // this contains the function foo
Note that not adding the parens is not calling the function. Therefore it should be obvious that when you do:
var bar = { foofoo : foo() }
What you're doing is passing the result of the function foo to bar.foofoo. The function is invoked without any "dots" in its invocation path. Therefore it doesn't belong to any object and therefore the rule of this == window applies.
On the other hand if you do:
var bar = { foo : foo }
What you're doing is assign the function foo to bar.foo. When you later call it as:
bar.foo()
the invocation contains a "dot" therefore the rule about the last object before the last dot applies.
See my previous answer to a related question for a detailed explanation on how this works in javascript: How does the "this" keyword in Javascript act within an object literal?

Javascript Function Declaration Options

I've seen experts using below to declare a function:
(function () {
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
//etc
}());
e.g.
https://github.com/douglascrockford/JSON-js/blob/master/json.js
Could someone help me understand when should we use above pattern and how do we make use of it?
Thanks.
Well, since ECMA6 hasn't arrived yet, functions are about the best way to create scopes in JS. If you wrap a variable declaration of sorts in an IIFE (Immediately Invoked Function Expression), that variable will not be created globally. Same goes for function declarations.
If you're given the seemingly daunting task of clearing a script of all global variables, all you need to do is wrap the entire script in a simple (function(){/*script here*/}());, and no globals are created, lest they are implied globals, but that's just a lazy fix. This pattern is sooo much more powerful.
I have explained the use of IIFE in more detail both here, here and here
The basic JS function call live-cycle sort of works like this:
f();//call function
||
====> inside function, some vars are created, along with the arguments object
These reside in an internal scope object
==> function returns, scope object (all vars and args) are GC'ed
Like all objects in JS, an object is flagged for GC (Garbage Collection) as soon as that object is not referenced anymore. But consider the following:
var foo = (function()
{
var localFoo = {bar:undefined};
return function(get, set)
{
if (set === undefined)
{
return localFoo[get];
}
return (localFoo[get] = set);
}
}());
When the IIFE returns, foo is assigned its return value, which is another function. Now localFoo was declared in the scope of the IIFE, and there is no way to get to that object directly. At first glance you might expect localFoo to be GC'ed.
But hold on, the function that is being returned (and assigned to foo still references that object, so it can't be gc'ed. In other words: the scope object outlives the function call, and a closure is created.
The localFoo object, then, will not be GC'ed until the variable foo either goes out of scope or is reassigned another value and all references to the returned function are lost.
Take a look at one of the linked answers (the one with the diagrams), In that answer there's a link to an article, from where I stole the images I used. That should clear things up for you, if this hasn't already.
An IIFE can return nothing, but expose its scope regardless:
var foo = {};
(function(obj)
{
//obj references foo here
var localFoo = {};
obj.property = 'I am set in a different scope';
obj.getLocal = function()
{
return localFoo;
};
}(foo));
This IIFE returns nothing (implied undefined), yet console.log(foo.getLocal()) will log the empty object literal. foo itself will also be assigned property. But wait, I can do you one better. Assume foo has been passed through the code above once over:
var bar = foo.getLocal();
bar.newProperty = 'I was added using the bar reference';
bar.getLocal = function()
{
return this;
};
console.log(foo.getLocal().newProperty === bar.newProperty);
console.log(bar ==== foo.getLocal());
console.log(bar.getLocal() === foo.getLocal().getLocal());
//and so on
What will this log? Indeed, it'll log true time and time again. Objects are never copied in JS, their references are copied, but the object is always the same. Change it once in some scope, and those changes will be shared across all references (logically).
This is just to show you that closures can be difficult to get your head round at first, but this also shows how powerful they can be: you can pass an object through various IIFE's, each time setting a new method that has access to its own, unique scope that other methdods can't get to.
Note
Closers aren't all that easy for the JS engines to Garbage Collect, but lately, that's not that big of an issue anymore.
Also take your time to google these terms:
the module pattern in JavaScript Some reasons WHY we use it
closures in JavaScript Second hit
JavaScript function scope First hit
JavaScript function context The dreaded this reference
IIFE's can be named functions, too, but then the only place where you can reference that function is inside that function's scope:
(function init (obj)
{
//obj references foo here
var localFoo = {};
obj.property = 'I am set in a different scope';
obj.getLocal = function()
{
return localFoo;
};
if (!this.wrap)
{//only assign wrap if wrap/init wasn't called from a wrapped object (IE foo)
obj.wrap = init;
}
}(foo));
var fooLocal = foo.getLocal();
//assign all but factory methods to fooLocal:
foo.wrap(fooLocal);
console.log(fooLocal.getLocal());//circular reference, though
console.log(init);//undefined, the function name is not global, because it's an expression
This is just a basic example of how you can usre closures to create wrapper objects...
Well the above pattern is called the immediate function. This function do 3 things:-
The result of this code is an expression that does all of the following in a single statement:
Creates a function instance
Executes the function
Discards the function (as there are no longer any references to it after the statement
has ended)
This is used by the JS developers for creating a variables and functions without polluting the global space as it creates it's own private scope for vars and functions.
In the above example the function f(){} is in the private scope of the immediate function, you can't invoke this function at global or window scope.
Browser-based JavaScript only has two scopes available: Global and Function. This means that any variables you create are in the global scope or confined to the scope of the function that you are currently in.
Sometimes, often during initialization, you need a bunch of variables that you only need once. Putting them in the global scope isn't appropriate bit you don't want a special function to do it.
Enter, the immediate function. This is a function that is defined and then immediately called. That's what you are seeing in Crockford's (and others') code. It can be anonymous or named, without defeating the purpose of avoiding polluting the global scope because the name of the function will be local to the function body.
It provides a scope for containing your variables without leaving a function lying around. Keeps things clean.

Is "this" necessary in javascript apart from variable definition

My question is dead simple.
I just casually discovered that once you have defined a property with this. into an object, you don't need to prepend this. anymore when you want to call them.
So this. is really meant to be used ad definition time, like var?
I found it my self shortly after, i was referencing the window object with this. since i called my object without using new, so like it was a function.
One extra question, maybe for comments. Inside the main object, if i create a new object, and use this during the object definition, this this what will be referring to?
No, unless the context of this is a global object, such as window. Take the following example:
function Foo(bar) {
this.data = bar;
console.log(this.data); // OK
console.log(data); // ReferenceError
}
In this example, you'll get a ReferenceError: data is not defined on the first console.log(data), unless, data is a global variable. To access the instance's public member, you have to use this.data.
References:
Understanding JavaScript’s this keyword
The this keyword
There are all sorts of circumstances where you MUST use this in order to reference the right data.
These two implementations do very different things:
Array.prototype.truncate(newLen) {
// sets the length property on the current Array object
this.length = newLen;
}
Array.prototype.truncate(newLen) {
// sets a global variable named length
length = newLen;
}
var arr = [1,2,3,4,5,6,7];
arr.truncate(2);
You MUST use this in order to control what happens if you want to modify the current object. Your assumption that you can leave it off and it will still modify the current object's properties is not correct. If you leave it off, you are modifying global variables, not member properties.
So this. is really meant to be used ad definition time, like var?
No, the point of this is to be the current scope of execution. You can (and will) run into weird errors if you don't use this. For example, imagine you are an object with a property val and then on the prototype of that object you have
App.obj = function(){
this.val = 'initial';
}
obj.prototype.myMethod = function(val) {
// how would you assign argument val to object val?
}
also note that your reasoning breaks down with methods.
obj.prototype.meth2 = function(){
myMethod(); // fails where this.myMethod() would work.
}
See http://jsfiddle.net/BRsqH/:
function f(){
this.public='hello!';
var hidden='TOP SECRET!';
}
var instance=new f();
alert('Public data: '+instance.public+ /* gives "hello!" */
'\nHidden data: '+instance.hidden /* gives undefined */
);
Variables created with var are hidden and cannot be viewed nor modified outside the function which created them.
But variables created with this are public, so you can access them outside the function.
I think I got it.
I defined my object as function My_Object(){...} and then called it with MyObject(). This way the My_Object was treated as a function, not an object and therefore this == window.
So in the end I was attaching properties and methods to window instead of My_Object! That's way there were available without prepending .this.
The right way to initialize My_Object as an object is to call it like this new My_Object, isn't right?

Categories

Resources