Why am I unable to modify 'this' in this context? - javascript

In the following case, I would assume that the value of this (which is a string) could be modified to a different string. That way, I could emulate an array and simply write string_var.shift() to remove the first character of the string. However, from what I've gathered, this is immutable. I'm not sure how else I would approach this problem if I am unable to modify the value of the string. I could of course return the result but then I'd have to write string_var = string_var.shift() which has a different syntax to the array function of the same name and would ultimately be confusing.
Object.defineProperty(String.prototype, "shift", { value: function() {
this = this.substr(1)
}})

You can't modify this since it is a keyword, not a variable. Just like function or class
you can assign that value to another variable:
var self = this.substr(1)
instead
Also, note that this context is the inner function at this point.

There are two reasons why the following code won't work. this is not a variable, it is a property of an execution context (global, function or eval) that, in non–strict mode, is always a reference to an object and in strict mode can be any value. It is syntactically invalid to assign anything to it.
But more importantly, it is impossible to implement a mutation method on the String interface, as strings, booleans and numbers are all immutable within Javscript, as per the ECMAScript specification. When you "mutate" a value, such as in the context x += 5, behind the scenes you are creating a new value, not modifying the original one.

Well you can return the value after doing some operations on it
String.prototype.shift = function() {
return this.slice(1);
};
var a = "abcdef";
console.log(a);
a = a.shift();
console.log(a);
Note:
modifiying the prototype of the language itself is considered to be bad practice

Related

confusion over how "softBind" function works

I'm currently studying javascript by following the "you dont know js" series.
In section "this & object prototype", the author came up with an way to soft bind this.
However, I am extremely confused by the code. So I was wondering if someone could kindly explain it to me, steps by steps, what the code really does?
//step 1: if "softBind" property does not exist on `Function.prototye`
if (!Function.prototype.softBind) {
//step 2: create a property named "softBind" on "Function.prototype" and assign to "softBind" the following function
Function.prototype.softBind = function(obj) {
//step 3: what is the point of assigning "this" to the variable "fn"?
//what does "this" represent at this point in time?
var fn = this,
//step 4: I understand that "arguments" is an array-like object, i.e. "arguments" is not a true array.
//But you can convert "arguments" to an true array by using "[].slice.call(arguments)".
//The thing I dont understand here is, why the 1?
//I understand it tells "slice" method to start slicing at index 1, but why 1?
//And what is the purpose of "curried" variable?
curried = [].slice.call( arguments, 1 ),
bound = function bound() {
//step 5: I understand what "apply" function does
return fn.apply(
//step 6: I dont really understand how "!this" works.
(!this ||
//step 7: utterly confused...
(typeof window !== "undefined" &&
this === window) ||
(typeof global !== "undefined" &&
this === global)
//step 8: if the above statements evaluates to "true", then use "obj",
//otherwise, use "this"
) ? obj : this,
//step 9: can't I write "curried.concat(arguments)" instead?
//why the convoluted syntax?
curried.concat.apply( curried, arguments )
);
};
//step 10: Why assign the "fn.prototype" as the prototype to "bound.prototype"?
bound.prototype = Object.create( fn.prototype );
return bound;
};
}
I'm very sorry for the long question, but I thought instead of dividing the question into several posts, it is more convenient if they are put into one place.
step 3: what is the point of assigning "this" to the variable "fn"?
The value of this holds a pointer to the currently executing function object. Only function objects can be held, so only things actually created through new() or equivalent notation. This can be useful for passing a reference to an outer object to an inner object created within said outer object.
Here's a minimal example:
function fn1() {
var x = this; // x = fn1.
this.u = 5;
function fn2() {
this.u = 10;
console.log(this.u); // Prints the member of fn2.
console.log(x.u); // Prints the member of fn1.
};
var W = new fn2();
}
var V = new fn1();
The output should be:
10
5
First, an object of type fn1 is created called V. It has a member variable u holding the value 5. Then, we create an object of type fn2 called W within fn1. It also has a member variable u, but here it holds the value 10. If we wanted to print the value of V.u within W, then we need a pointer to V. Calling this.u within W would output its u value (10), which is not what we want. So we define a variable x within the scope of the class fn1, holding the this pointer for us. Now it's possible to access the members of fn1 within fn2.
Step 4
The first argument is the object being bound to. You don't want to pass that to the function being bound, that would break its functionality, for it does not expect an extra argument prepended to its normal list of arguments. So, the first argument has to be removed.
step 6: I dont really understand how "!this" works.
!this is simply a way of checking whether this is defined. If it is not, then the value will be true. Otherwise, since this
would be an object (which evaluate to true when cast to a boolean), then it is false.
step 7: utterly confused...
Here, the original author checks if this is equal to either window, or global. Note; In modern browsers, checking for just window is enough, but IE exists (as do non-browser javascript environments). So, the full statement evaluates to this thing:
If I am not called from within an object, or if I'm called from the object window or global, then return the object softbind was created with. Otherwise, return the object I was called from
Note that this is exactly what the author of the original article wants. When a library function is called with this special binding, then we can be sure that whatever the library does; it can't access the global context through the use of the this variable. But, it can access any other object, allowing you to interface with the library.
step 9: can't I write "curried.concat(arguments)" instead?
Curried holds all arguments the original softbind function was called with, except for the first argument. arguments , at this point, is not equal to arguments in the earlier call. Here, it refers to the arguments the bound function is called with, not those it was bound with. This line integrates the two sets of arguments, allowing you to provide default arguments. The trick used here is to concatenate the arguments, e.g. Suppose your function has default arguments [1,2,3,4] and you supply [5,6]:
[1,2,3,4].concat([5,6]) produces [1,2,3,4,5,6].
Why not simply concatenate, and use the prototype? Arrays are passed by reference in javascript, so this will keep curried the same, while concatenating arguments to the call. Equivalently, you could write this:
curried2 = curried.concat(arguments);
return fn.apply(
(.....)
curried2);
Admittedly, the terseness does not help the understandability of this example. Simply re-naming arguments to calledArguments and curried (an advanced math term not relevant to the explanation) to be defaultArguments and using a simple for loop over each argument would be far easier to understand, if a little more verbose. I guess the author wanted to be fancy.
step 10: Why assign the "fn.prototype" as the prototype to "bound.prototype"?
Go up a bit on the article to the part where the author talks about the default bind function and how it works: basically, the end result of replacing the prototype back with the default prototype during the function call means that when your softbind enabled function is called with the new operator this will be set to itself, rather than the default bound object. prototype will not work when simply calling the bound function.
It also enables inheritance, meaning that creating things for a softbind enabled function using its prototype will not have that prototype be overruled by that of softbind when it is bound. (That would make softbind incompatible with prototypes). Instead, both prototypes are used.
Also see this reddit post.
A word of warning
We're extending the language with new features here. Features that aren't exactly necessary, and are largely concerned with semantics. If you're just interested in learning the language, this really goes way too far, you don't exactly need special binding semantics. Worse, it can be confusing if this does not behave in a way you expect it to.
A simpler alternative
Enable strict mode. Now this will default to undefined whenever it points to the global object. Prevents the problem this convoluted code is trying to solve (by usually resulting in errors from functions trying to access member variables or functions of undefined), while at the same time being far easier to use, and at the same time it will complain about a lot of syntax that is valid regular javascript, but a bug in any normal use-case. Also see the MDN article about it. It will catch a lot of potential errors for you instead of silently doing nonsensical things.
Another alternative
bind tries to resolve 'losing' the object when you pass a member function of it to another function, such as setTimeout. Another way of doing it is by using an anonymous function. Instead of using (soft) binding, assuming obj is an object holding a function fn being passed a parameter param;
setTimeout(obj.fn(param), 500);
You can use:
setTimeout(function(param){obj.fn(param);}, 500);
Which avoids the problem through a layer of indirection by passing an anonymous function. Also see this question.

Why are JavaScript function objects allowed to differ from the string to value map format?

In JavaScript, objects have properties and values:
var o = {
prop1: "value",
prop2: 3
}
My understanding is all JavaScript objects must look like this (i.e. have properties and values only). But, functions (I'm not talking about methods) are objects too:
function f() {
console.log("Hello");
}
Why is it possible for my function object to differ from the {property:value} style of object that is o?
Update: To try to explain my question further:
Objects are described in almost every book I've ever read as string to value maps. For example, they map a property name to a property value:
{
property1: value,
property2: value
}
Functions are objects, however they do not look at all like string to value maps:
function my_f() {
// code here.
}
Why are function objects allowed to differ from the string to value map format?
Well, In javascript, functions can be treated as Classes in other Object Oriented Languages.
This means that you can instantiate a new object from the function using the new keyword
Example:
function myFunc(){
//Some code goes here
}
var myObj = new myFunc();
You can attach properties to this Class using this keyword
Example:
function myFunc(){
//this is a public property for any myFunc object
this.name="My_Name";
//this is a private property
var age = 22;
}
var myObj = new myFunc();
console.log(myObj.name); //Will output "My_Name"
console.log(myObj.age); //undefined
Everything is object in JS.
var o = {
prop1: "value",
prop2: 3
}
is just a shortcut for object creation instead of using the Object constructor(and is fast too). Same goes with functions.
Consider
var adder = new Function('a', 'b', 'return a + b'); console.log(adder.prototype)
Its an object with the constructor and other properties with corresponding values.
I think what you're asking about is, at its heart, the difference between a function declaration and a function expression. These are just different ways that Javascript allows variables/properties of type Function to be created.
You can, of course, define a function as the inline value for a property, as you would any object literal:
var Foo = {
bar: function(){
console.log("bar");
}
};
You can also define as a property this way:
var Foo = {};
Foo.bar = function(){
console.log("bar");
};
Or you can assign the result of the function expression directly to a variable:
var bar = function(){
console.log("bar");
};
These examples should demonstrate that functions are like any other variable/property in Javascript. They have a type, just like a String or a Number. A string is also an object, but you don't need curly braces to create a string:
var foo = "foo";
A function declaration, as you're describing in your question is a slightly different way of defining a function:
function bar(){
console.log("bar");
}
I believe that they included this additional function syntax in the language for one main reason: hoisting.
Including this alternate syntax that hoists function declarations "up above" other expressions allows coders to be a little bit more loose with the order in which they define their variables and functions.
There are arguments to be made both in favor of function declarations and function expressions, but I tend to use the function expression syntax, as I like that it is more consistent and less surprising for new team members.
UPDATE:
Perhaps you are overthinking this idea that "Objects are described in almost every book I've ever read as string to value maps. For example, they map a property name to a property value:"
A string is an Object, a function is also still an Object. Try this:
var foo = "foo";
foo.bar = "bar";
console.log(foo, foo.bar);
Or this:
var foo = function(){
console.log("foo");
};
foo.bar = function(){
console.log("bar");
};
console.log(foo(), foo.bar());
The syntax for creating object literals in Javascript can involve defining the key/value pairs, yes. But there are lots of ways to create variables and properties of various types, many of which ultimately inherit from the Object prototype, including the Function type.
The different syntaxes all result in the same types of Objects being created. The only thing that matters is the order of declaration/execution, as defined by the hoisting rules.
After 5 minutes of looking into your question with a wierd look i think i finally understood what you want to know.
You, in-fact, ask why is the consistency of the Object in javascript is different when using function or key:value kind of option.
Well, javascript is a
dynamic, weakly typed, prototype-based language with first-class functions
If I can quote wikipedia here.
This means that everything in this so-called language is Object base, if you know c# from example, its like everything is object type and there aren't any other primitive-type objects.
With that being said, object is mostly like a memory entry and not a real value of things, unlike int, string, char etc.
Therefore, functions are actually stored in memory as same as objects do.
if you look on other elite-type languages you can see that object there can store perhaps everything, even an entire solution, it doesn't have any bounds.
In unrelated matter, I would like to recommend you to read about "boxing" and "unboxing" of elements to understand the idea behind objectifying stuff.
Why are function objects allowed to differ from the string to value map format?
Exactly because its just a memory reference and the "syntax" isn't really important, if you try to execute some operation that belongs to a method and not for a normal type object like {key: "value"} the execute will first approach the object in the memory and try to operate () on it, it will throw an error unless the () operation is defined for this object.
hope I made myself clear enough
EDIT
ok, ill explain more, as you wish.
basically there are 2 ways in which data storing is occurring.
Heap memory (not the data structure), if to quote Wikipedia again is
very simple explanation is that the heap is the portion of memory where dynamically allocated memory resides
In easy words, it means you save something by its value and you use it in different ways as value.
so you ask yourself, what does it mean "not by value"
Memory reference (stack), that means that every non-primitive object you create is assigned with its own memory address, in fact every time you create an object you're allocating space in your memory, just to be clear, all javascript's data storing is done by this way, unlike any elite-type language such as java,c,c++,c# and so on..
now, why am i saying this?
because when i create an object, a reference, i can create a reference to whatever i want to, it can be an object that describes Human, function, document or even a file. I will be very careful with what im about to say, javascript doesnt let you distinct between objects, an object is an object, of course each has its own properties, but that is only important when you try to execute things with that object.
if you are familiar with c# (always bringing this up because its commonly wide-spread language) you'll notice that you have both objects that you create, methods, threads,task,solutions and possibly every type of data, and they are all objects before they are themselves.
as to conclude:
object in javascript is a matter of principle and not data type.
encourage you strongly to read an article, heap vs stack
After doing a little more research of my own, I found out function objects are a special type of object. Aside from being a regular object which has any number of properties and values, function objects are also callable blocks of code. This extra "capability" (I couldn't think of a better term) is something that is added by JavaScript itself.

Get name of instance of a class within the class

Here is what I want:
var Validator = function () {
this.do = function () {
alert(INTANCENAME); /// SHOULD BE 'FOO'
}
}
var FOO = new Validator().do();
Is it possibe to implement in Javascript?
The truth is there is no point of doing that, the only way I can hardly think is to loop all window or scope objects and check some kind of equality with the current object, something like
this.do = function () {
for(var key in window) {
if(this === window[key]) {
alert(key);
}
}
};
In order to work call it after you assign it.
var FOO = new Validator();
FOO.do();
Another issue that can come up is that an instance (a reference) can be stored in various variables so maybe will not get what you expect.
The literal answer to your question would be:
Use (new Error()).stack to get information on the line and the function where the do() method was called.
Use JS parser (e.g. Esprima) to find out what variable it was called on (if any, the method itself might be assigned to a variable).
I do not recommend doing this though.
There's no way to directly do what you're asking for here. Objects themselves are not in any defined by their matching variable name - in fact it's possible to have objects that exist that are not directly assigned to a variable, and multiple variables assigned to the same object.
The javascript interpreter uses our variable names as identifiers to help with the code execution, but once it's running the variable name makes no difference to the running javascript program, as it's probably been reduced to a memory reference by the time it's executing, completely separated from the original code that you wrote.
Edit: Answer by yannis does kind of simulate this, but it relies on working with variables available in a specific scope - what I ment was that there's no direct way to do this from within the object itself as per your example in the question.

Defining Functions in Object.create()

I want to create an object just using the Object.create function (without any prototype, first argument as null).
I read somewhere that properties determine the state of an object in JavaScript and JavaScript has three different kinds of properties:
named data properties
named accessor properties
internal properties
So when I define a function in an object, should I always define it as a named accessor property:
var obj = Object.create(null, {
a:{
get:function(){
alert('jQuery nyan!');
}
}
});​
Or should I just define the function as a named data property when it is neither a setter nor a getter? [e.g some jQuery functions that makes changes to the DOM obj]
var obj = Object.create(null, {
a:{
value:function(){
alert('jQuery nyan!');
}
}
});​
Which approach should I take? In terms of performance (speed) and memory management do they have differences? They both appear to work without any exception.
obj.a;
//output: 'jQuery nyan!'
To make it easier to refer to them, let's define them as follows
var objA = Object.create(null, {a: {get: function(){alert('jQuery nyan!');}}});
var objB = Object.create(null, {a: {value:function(){alert('jQuery nyan!');}}});
Now, there is almost no difference between the invocation of objA.a vs objB.a(), except the use of ().
There are some differences, however.
The main difference is that you can't pass parameters to a getter, it is invoked as-is. This means objA.a(1,2,3) will not invoke the function with arugments 1, 2, 3. It will in fact throw an error after invoking, assuming the getter does not return a Function (you're effectively trying to do undefined(1,2,3)).
A second difference requires us to remember Object.create's second parameter takes an object of descriptors, which includes the flag writable (which defaults to false). The difference here is you can not set writable:true on objA.a because "A property cannot both have accessors and be writable or have a value". This means that if you want the method of the getter changed, you must re-define the property, whereas for value you could enable the use of = to change the method associated with the property.
Additionally, with no setter objA.a = <expr> will not perform any action at all.
Normally, you'd only use getters and setters in the following instances, with value as the standard behaviour otherwise;
Lightweight calculating an output
Validating input (to protect an object)
Hiding a variable from direct access
Keeping a standard API where variable or property names may change
If you don't care about compatibility, using getter and setters could be a good approach to replace setNAME()s and getNAME()s. And there is no significant performance gain/loss comparing to function version.
Note that, cause it looks like accessing an variable, instead of calling a function, so the getter/setter function should be very light weight to meet this expectation.
And don't ever use one function for both getter and setter like jQuery does, it's simply very slow. As there is no function signature in javascript, simulate it with if/else will cause lots of performance loss.

Pass a function reference that has a variable as its name

I have the following javascript method:
function 123_test_function(){
}
The function is generated by java and sent to the client. The 123 is the id of the component so it could change. i.e I can have another function called 111_test_function()
I want to pass this function as a reference.
So I need to create the reference
var 123_test_function = function 123_test_function(){
}
In another js file inside an object I have a function that needs to use the 123_test_function reference like so:
useFunction(123_test_function);
The problem I'm having is which the 123 part of the function.
In this object I have a variable(uniqueID) which has the number at the beginning of the function.
I need the function call to be something like:
useFunction(uniqueID+"_test_function");
This doesn't seem to pass a function instead it passes a string.
Am I doing something wrong?
For one, identifiers (such as function names) cannot begin with a digit.
To solve your problem, use an object, like this:
// 1. define an object to hold all your functions
var allFunctions = {};
// 2. store any function with a unique string as the ID
allFunctions['123_test_function'] = function () {
// whatever
};
// 3. call the function
allFunctions['123_test_function']();
allFunctions[uniqueID + '_test_function']();
Objects are associative arrays. They store key/values pairs, so they do exactly what you want here.
Note that functions don't need a name in JavaScript, so I did not use on in step 2.
If the function is defined as global one, it will be a member of global object (window in case of browsers). Hence you can just do window['id_'+uniqueID+'_test_function'] to access your function
useFunction(window['id_'+uniqueID+'_test_function'])
(Identifiers cannot begin with numbers in JavaScript so I added the 'id_' prefix. You can of course change it to your liking.)
function test_function(number){
if(number == 1)
{
return function() {}
}
if(number == 2)
{
return function() {}
}
}
call the function like this
var func = test_function(1)
func();
As a couple of people have correctly pointed out, a function (or indeed variable) name cannot begin with a numeric. Also this syntax is wrong:
var 123_test_function = function 123_test_function(){
}
The correct syntax would be:
var 123_test_function = function() {
};
...although it should also be noted that the effect of this is exactly the same as a "traditional"
function 123_test_function() {
}
...declaration, in the context of the window object - since window is effectively the global scope of a JS environment in a browser, it doesn't matter how you define the functions, they will always be accessible from anywhere. Understanding exactly what each method of declaring a function means in Javascript is important - luckily, Douglas Crockford to the rescue once again...
People have suggested various methods for calling your named functions from the context of a string, which is basically attempting to use "variable variable" syntax, a subject that has been discussed on SO and elsewhere at length. The eval() approach should be avoided wherever possible - if you find yourself needing an eval() chances are you went wrong somewhere a while back. #Tomalak has the right idea with a collection of functions held in an object, but this still needs the slightly messy string approach to reference things that are actually being accessed by a numeric ID. The collection approach has the advantage of not cluttering up the window object with what are likely to be single/zero use members.
But the way I see it, all you actually need here is an indexed array of functions, where all you need is the numeric index in order to access them. I suggest you create your functions like this:
// Do this once at the top of your JS
var test_functions = [];
// Now, for each function you define:
test_functions[123] = function() {
// Do stuff here
};
// And when you need to call the functions:
var funcId = 123;
test_functions[funcId]();

Categories