change JavaScript scope - javascript

Is there any posibility to exchange the special global window scope by a custom one? I just thought with is meant to, but it only stacks another "lookup" scope. Eg.
test={};
with(test){
a=1;
}
does not create the property test.a but window.a.
So the window object has a JS-specific special quality I cannot recreate with own code?

If the property exists on the object given to with then it will be modified, but it will never be created. This is a major "gotcha" with using with and the primary reason it should be avoided.

With with only if the object passed in has that property, will it be modified. It will not be created.
http://www.yuiblog.com/blog/2006/04/11/with-statement-considered-harmful/

Related

Accessing parent scope value with standard method

Today I wondered after some strange behavior of angularjs. I used console.log to log $scope, there were no key attached to scope named val1, but when I use console.log($scope.val1) its returning value as a object. After digging out the reason, I found that it was accessing parent scope as there is no kay named val1 in $scope. Now my question is that,
Which is good practice? Can you please justify?
Using $scope.$parent.val1
Using $scope.val1
You should generally never use $scope.$parent and instead rely on Javascripts prototypal inheritance. By accessing the parent directly, you run the risk of the code breaking if you move the directive/controller a step up in the scope hierarchy, and the data is now on $scope.$parent.$parent instead.
Instead, never write to properties directly on the scope but to objects on the scope object instead.
Say you do:
$scope.$parent.value = 'x';
Then you do:
console.log($scope.value);
That'll print x to the console. If you then do:
$scope.value = 'y';
You're not modifying the value property on the parent scope, but introducing a new property on the child scope. So $scope.$parent.value will still contain x.
To get around that, you do:
$scope.$parent.data = {value: 'x'};
console.log($scope.data.value); // prints x
$scope.data.value = 'y';
console.log($scope.data.value); // prints y
console.log($scope.$parent.data.value); // also prints y
The reason this works is that instead of creating a new value property on the child scope, it first needs to lookup the data property. And that's not on the child scope, so it goes up the prototype chain ($parent) to find the data object. The data object is found on the parent, and the value property is set on that object instead.
It depends on the type of val1, in case it is a primitive, you will have to access it explicitly via $scope.$parent.
In case it is an object, you can take advantage of the prototypal inheritance that exists between parent and child scope in Angular and just reference it regularly, as I am sure you are aware of, objects are passed by reference, so any change to the object will change it on the parent scope.
More info here

Why do variables become keys on the window object?

I've noticed that variables become keys and their values become values of said keys when I am writing on the window object. For instance:
var variable = "value";
console.log(window.variable);//logs "value"
But if I create a new object of my own like:
var o = {
key: "value",
var key2 = "value2"
}; // result: "syntax error"
I have to use the colon to set key/value pairs. And even with constructor functions, although I don't get a syntax error, I don't seem to be able to do this inside the constructor function or during object instantiation or after:
function Blueprint(){
this.key = "value";
var key2 = "value2";
}
var o = new Blueprint;
console.log(o.key); //result: "value"
console.log(o.key2); //result: "undefined"
Now, I understand why, in the former case, I generated a syntax error and why in the latter case I was unable to attach key2 to the Blueprint constructor function but what I don't understand why on the global window object I am given free range to just add properties using variables and they instantly become keys on the window object. Other than on the windows object, variables seem to behave as though they are independent of objects and property creation.
I've also noticed similar behavior on the global object when experimenting with node. Are global objects the only objects that can set key/value pairs in this way using variables? And if so, why? Why aren't we forced to do something like the following when working on the global level:
this.key = "value";
Or...
window.key = "value";
Is this just some caveat to the behavior of the language overall or is there some internally consistent logic about the window object in relation to all other objects that explains this?
Global variables (as opposed to local variables declared within a function) become properties of the global object.
In a browser, the global object is window.
The global environment is a so called Object Environment (Record):
Each object environment record is associated with an object called its binding object. An object environment record binds the set of identifier names that directly correspond to the property names of its binding object.
As you can see, the behavior to create properties for identifiers is explicitly defined. And in the case of the global environment, the binding object is the global object, which is window in browsers.
More detailed information about environments can be found in the spec:
There are two kinds of Environment Record values used in this specification: declarative environment records and object environment records. Declarative environment records are used to define the effect of ECMAScript language syntactic elements such as FunctionDeclarations, VariableDeclarations, and Catch clauses that directly associate identifier bindings with ECMAScript language values. Object environment records are used to define the effect of ECMAScript elements such as Program and WithStatement that associate identifier bindings with the properties of some object.
I can't tell you why these two types exist. If you want to know that, you could ask at http://esdiscuss.org/

What is the difference between window and this.window, in javascript?

I'm looking at a complex bit of JavaScript, which is doing all sorts of runtime/dynamic manipulation of objects and scripts. In the process, I'm learning all sorts of minutiae about Javascript and its idiosyncrasies.
This one has me stumped, though. Is there ever a situation where
window !== this.window; //true
In other words, when would you ever write this.window instead of straight out window?
"Is there ever a situation where window !== this.window; //true"
Sure, whenever this refers to an object without a .window property or with a .window property that doesn't point to the global object (assuming a browser environment where window is the global).
"...when would you ever write this.window instead of straight out window?
When this refers to an object where a .window property is anticipated not being a reference to the global.
this is not implicitly searched for names in javascript like it is in C++ and java.
in javascript, referring to something foo instead of this.foo or someobject.foo, tries, in order, any var-declared variables, then the global namespace.
this.var looks up only members of this (and its prototype, and the prototype's prototype and so on)
at the top level in a script, this refers to the default global namespace, which is the window object, and that's where you stay until you call a method with foo.meth(). window contains, oddly enough, a member called window which points to itself. So you can generally go:
window.window.window.window.location = "some_url"
if you like. In fact an awful lot of the names that you assume are "just there" are members of the global object, e.g.
Object === window.Object
If you like you can say
var window;
to declare a variable called window which hides the global window within that block of code. But don't do that.
I believe you can actually change what the global namespace is as well, but I don't recall how.
Well, it's a duplicate, but this refers to the global scope when you're in the global scope (err), and the global scope is window. (so this == window and window.window == window are true)
If you're in a function that's being used as a constructor, for example (new Pie()), this no longer refers to the global scope, but rather the object that is created. What this is really depends on where you're running code.

Why we used "this" keyword in this snippet?

var someObject = {
someArray : new Array(),
someInt : 0,
Total: function(){
this.someInt = 0;//we used "this" keyword here, why?Cant we just say "someInt = 0"?
for(var i=0;i<this.someArray.length;i++){//and here..
var c = this.someArray[i];//again we use "this"
this.someInt += c.value;//also here
}
so why did we use "this" keyword? cant we just type the name of the variable?
The this keyword refers to the object on whose behalf the call is made later on, i.e. if you call the function like this:
someObject.Total()
then this will refer to someObject inside the function. Thanks to this keyword the function can modify someInt and read from someArray which are members of someObject. If you dropped this from the function body, all those references would be to global variables or variables local to the function body.
No, the statement someInt = 0 would not modify the someInt property of someObject. Instead, it would modify a property named someInt on the global/default object (window in a browser), which is obviously not want you want.
Note that (depending on how you intend to invoke the Total function) you could also write this as someObject.someInt. However, when calling the function like this:
someObject.Total()
...the value of this in the function is equal to someObject.
No, because the variable is not fully created. By using the 'this' keyword you can access a variable from itself.
Looks to me like it's just for clarity. Always using this. is probably a good practice when you don't use special naming conventions for instance variables vs. local variables (in other languages as well, not just javascript).
Even though it may not be required in this case, if you had a larger function, with lots of local and instance variables, it makes things much clearer when you distinguish.
In fact, Douglas Crockford in his Javascript The Good Parts, suggests not using this keywords in the code, for the functions from the object may be applied to other objects and this may cause errors. so it's better sometimes to use just variable names.
someInt is defined as a property of someObject. It would need to be defined as a variable in order to access it that way.
http://jsfiddle.net/Z7mSK/
Understand this keyword in detail HERE

prevent access with setter

The problem is to prevent overriding from outside of a object.
my idea is to use setters:
var spot = function(val){
this.id = val;
this.__defineSetter__("id", function(val){alert("bang");});
}
The id should be set once in the constuctor and never be changed.
I would also like to define the setter on the prototype because I have 10.000 spots. But in this case the setter prevets access also to the consructor.
I am not willing to use var id in the constructor and define a getter on it. In this case every single one of the (10.000) objects has its own closure.
A second question is: Can the setter somehow know wether the var is changed from the constructor or later from a (spot)internal function? So I could prevent access just from outside the object.
Firstly, that code is non-standard and deprecated. Depending on the platform you're developing for, I suggest using preventExtensions or freeze. Or maybe you just want to define the id property as read-only, in which case use defineProperty.
Secondly, as you've done things, each instance of spot already has it's own closure. That setter that you defined is a unique function + lexical scope that will exist for every spot, aka closure. So I'm not sure what the big deal is with making a getter as well. Although the first point trumps here, and you should be using the new methods to achieve that functionality.
Lastly, no matter what direction you take, the setter will not be able to "know" anything. So you can either have a separate variable, something to the tune of isInitialised, or create a code invariant so that the value is undefined at first, and numeric afterwards, which allows the simple check if the variable has a defined value, in which case it's been set, and shouldn't set it again.

Categories