Function object in JavaScript - javascript

I think the Function object is the only instance in the JavaScript. All the other function(){...} or var xx=function(){...} are the objects inherited from this Function object. That is the prototype based language feature. And in prototype based language there is no Class, and One of the advantages of it is the object can changed anytimes.such as add a method or add a property into it. So, I think we can treat object like a key-values collection. You can add items into it anytimes after you created it. (If I was wrong, Please correct me.)
Say you have the code:
Function.test=function(){
alert(Function.name);//"Function"
alert(Function.myName);//"fun"
};
Function.name="fun";
Function.myName="fun";
Function.test();
In the above code, all I want to do is add a test method to the Function object.
There is no error found in this code. But why Function.name can not be changed?

First of all this property is not standard. This means that different browsers may treat it as they want. The second thing is that according to MDN it is read only.

A page from MDN states that the name of the Function cannot be changed because it's read only.

Related

difference between using setters or methods in javascript

I am reading about getters and setters in javascript. I would like to know if there is a difference between this two ways of coding with and without setters
first way, without setters.
>obj1 = {
arr: [];
}
>obj1.arr.push('first')
>obj1.arr
[ 'first' ]
Second way, with setters.
>obj2 = {
set add(data) {
this.arr.push(data);
},
arr: []
}
>obj2.add = 'first'
>obj2.arr
[ 'first' ]
The setter syntax in your example does not really prevent the client code to still add a value using the direct push call as in the first code block. So the difference is that you just added another way to do the same thing.
To make a fair comparison, you would have to define the same method in both alternatives: once as a normal method and once as a setter method, and then the difference is just the syntax how the argument is passed to the method, either with obj.add('first') or obj.add = 'first'.
In this actual case I would vote against the setter, because it gives the false impression that if you "assign" another value, the first assigned value is overwritten:
obj.add = 'first';
obj.add = 'second';
... but obviously this is not the case: both values exist in the object now.
First, The set Syntax bind an object property to a defined function. In this particular example, there is no difference between two codes, but let's say for example you want to check if the value is negative before adding it to the array, so you can use set to Encapsulate that behavior.
So basically, using setter is only to add additional encapsulated behavior to the functions of the objects.
The way of accessing the array index called bracket notation. it is equal to dot notation, except the bracket notation allows you to set new properties to objects or arrays dynamically.
Hope this help you.
I think difference only about "how it looks like". Using setters it's closest way for understanding for people who came to js from object oriented languages.
The getter/setter property is not the same as "normal" instance property, one is called "named data property", the other is called "named accessor property".
Please let met quote below part of documents from the ECMAScript 5.1.
https://www.ecma-international.org/ecma-262/5.1/#sec-8.10.1
An Object is a collection of properties. Each property is either a
named data property, a named accessor property, or an internal
property:
A named data property associates a name with an ECMAScript language
value and a set of Boolean attributes.
A named accessor property associates a name with one or two accessor
functions, and a set of Boolean attributes. The accessor functions are
used to store or retrieve an ECMAScript language value that is
associated with the property.
An internal property has no name and is not directly accessible via
ECMAScript language operators. Internal properties exist purely for
specification purposes.
There are two kinds of access for named (non-internal) properties: get
and put, corresponding to retrieval and assignment, respectively.
And
If the value of an attribute is not explicitly specified by this
specification for a named property, the default value defined in Table
7 is used.

How to use toHaveBeenCalledWith on an object assignement

Until now I have been using the following construct quite a lot:
spyOn(ClassToSpy, NameOfMethodToSpy);
...
expect(ClassToSpy.NameOfMethodToSpy).toHaveBeenCalledWith(ObjectToCompare);
But now I would like to check the call to an exported object and not an exported function. Is this also possible with karma/jasmin?
To be more specific:
I have a service which gives me a reference to the global native browser window object:
get nativeWindow(): any {
return window;
}
My code under test does the following with this returned window object:
this.winRef.nativeWindow.location.href = clean_uri;
Now I want do be sure that this href property of the location has received the new url. As there was no function involved in this last call I can not use the toHaveBeenCalledWith-construct from karma/jasmine.
I don't know exactly the answer to your question if it is possible to spy on plain exported objects. I guess it is not possible. But you have mentioned that you already have a service in place which wrapps the access to the window object. Therefore I would suggest that you add some getter / setter methods to this service in order to access the object. This way you can use the well known behaviour of spyOn(...) for functions.

Reusing functions of a prototype

i'm reading the book 'Secrets of the JavaScript Ninja' (http://jsninja.com/) and wonder why a certain code block from one of the examples is coded like it is.
The example (http://jsfiddle.net/3s5bopqe/3/) builds a custom array type (MyArray) and reuses a number of functions from the Array.prototype without actually inheriting from the 'Array' type.
In the example from the book a function with a certain name is reused in the prototype of the custom type using this code
MyArray.prototype[ name ] = function() {
return Array.prototype[ name ].apply(this, arguments);
};
I believe i understand what happens here. But it seems unnecessary to me to actually use a function literal and explicitly 'apply' a function from the Array.prototype. The following code works just as well in the test setting :
MyArray.prototype[ name ] = Array.prototype[ name ];
My question is whether there are any advantages of using the code from the book over the last code block ?
By using
MyArray.prototype[ name ] = Array.prototype[ name ];
you are actually copying method from Array into your object (MyArray).
In future, if Array method changes, your MyArray method wont be updated.
By using
MyArray.prototype[ name ] = function() {
return Array.prototype[ name ].apply(this, arguments);
};
you referred to Array method. Changes made in Array object methods are reflected in your MyArray methods. Why? Because you never copied that method, you just borrowed it (referred to its current implementation).
There's one major difference I can see. If any of the targeted methods on Array.prototype gets altered after you copied them (e.g. applying a polyfill that fixes behavior) the changes will not be reflected using MyArray.prototype[ name ] = Array.prototype[ name ]; while it would using the jsninja approach.
Depending on your point of view, you may find one or the other behavior more fitting.

Difference between defining and assigning property

What is the difference between assigning a property to an object and defining it?Which one is better and how?
This
Object.defineProperty(obj,p,propDesc)
Or simply
obj.p="someValue";
Object.defineProperty lets you set a whole bunch of options about that property. Like enumerable and writable.
When you do obj.p = 'something';, you're setting a property with the "default" options.
Neither is "better", they each have their own uses. Which one you use depends on your requirements.
As found on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
"
This method allows precise addition to or modification of a property on an object. Normal property addition through assignment creates properties which show up during property enumeration (for...in loop or Object.keys method), whose values may be changed, and which may be deleted. This method allows these extra details to be changed from their defaults."

What is a reverse reference to the DOM object?

In this link: http://css-tricks.com/snippets/jquery/jquery-plugin-template/ it has a line of code that says
// Add a reverse reference to the DOM object
base.$el.data("yourPluginName", base);
what does the "reverse reference to the DOM object" mean?
Assuming that you know the jQuery data function:
It's storing a reference to the instance of the class in the data cache of jQuery, meaning that the stored instance can be used to access the initial base object if it in the current context is not available.
This way, the class instance can be used later. However, the use of the prototype keyword upon the initial class that the instance were created from will modify the instance.
EDIT:
Ooops, it seems that Anurag is right, and I was giving wrong information.
Sorry, the information I gave in initial answer was not completely correct. I've updated the answer, so it now tells the truth.
In the comments you're asking:
so you mean its storing the current state of "base" in the data cache but if we make changes to "base" later on then the one in the data wont be affected? so if for some reason we needed to get the original one again we can do data('yourPluginName') to retrieve it? can you give me an example of when this would be helpful?
It seems that none of the statements are correct.
As I did obviously not remember adequately, the thing stored in data is only a reference to the object:
var obj = {};
obj.hello = "Hello";
$("#someElement").data("object", obj);
obj.world = " world.";
alert(
obj.hello +
$("#someElement").data("object").world
); // alerts "Hello world."
BTW, JavaScript variables with names like this base-thing (but, more often seen as that or similar) are typically used to represent the current context, accessed through the this keyword, which on many occasions is more easy to store in another variable due to scoping/context changes, that will make the current context and therefore this, change.
Also due to issues with context, the stored value in data could be used to access the specific object instance from another context (that is, when this represents something else), instead of the version of the base object that was continually used after a copy of it was stored.
I hope this answered you questions :D
The technique and the problem it solves is general and not specific to jQuery plugins. There may be cases where a Javascript object corresponds to a DOM element, and wraps logic specific to that DOM element. This object might be interested in listening to events such as clicks that happen within that DOM element. The information we get in those callbacks is the element that triggered it, and not the associated object. You could use jQuery's data API or any type of map in general to retrieve the corresponding object, and do something with it.

Categories