I'm posting due to a lack of understanding of a couple of concepts and also to check if my description of this code is accurate.
First I have created parent object called contactForm. I've made this object equal to an object literal which uses literal notation that is, creating a new object with { } and defining properties within the brackets.
Then I have the init method. If you’re familiar with object orientated programming that would be the same things as your constructor method.
Now the next part is where is where I am confused. I am using jQuery to create a new element which are the button tags. Is this newly created element an object inside of the parent object called contactForm?
My second question is am I passing a parameter that sets the text to 'Contact Me!' to the contactForm object or the button element/object?
My final question - is it the case that the parameter passed to the object can also be called a property of that object?
Sorry if I haven't been descriptive enough or accurate enough with my terminology. Any succinct and clearly explained answers would be massively appreciated.
var contactForm = {
init: function() {
$('<button></button>', {
text: 'Contact Me!'
})
.insertAfter('article:first');
}
};
First I have created parent object called contactForm. I've made this object equal to an object literal which uses literal notation that is, creating a new object with { } and defining properties within the brackets.
You have an object, which is described in your code by an object literal, and assign that to the variable contactForm. Not sure why you would call it "parent".
Then I have the init method. If you’re familiar with object orientated programming that would be the same things as your constructor method.
Your object has a property named "init", which is a function - conveniently this is called "a method". However, constructors in JavaScript work a bit different - every function can construct objects when it is called with the new operator. Of course, a dedicated method to initialize is often used when singleton instances are declared (as literals).
Now the next part is where is where I am confused. I am using jQuery to create a new element which are the button tags. Is this newly created element an object inside of the parent object called contactForm?
No. What you are doing in the init function has (at first) nothing to do with the contactForm object. You are calling the jQuery function, and it returns an object on which you call the insertAfter method, and as you don't do anything with the result of that function it is garbage-collected.
My second question is am I passing a parameter that sets the text to 'Contact Me!' to the contactForm object or the button element/object?
You are passing two parameters: a string and an object. What the jQuery function does with these arguments is unknown to your code. According to the documentation (and to the code, if you really wanted to dig in), this will create a button element (wrapped in a jQuery instance) and call the text method on it.
My final question - is it the case that the parameter passed to the object can also be called a property of that object?
No. You pass parameters into a function. It might happen that the function sets them as properties of a returned object, but that depends on the function. Anyway they are not called "properties of the function object".
Related
A bit of confusion on how static works in javascript.
function StaticExample() {}
StaticExample.staticProp = "Hello"
console.log(StaticExample.staticProp) // "Hello"
Here I have created a function and then created a static variable staticProp (not if we can call it static though). This adds the field staticProp to the constructor field on StaticExample's prototype
Question 1: Is there a specific reason to this behaviour(field getting added to the constructor property)?
Now the constructor is rewritten as below.
StaticExample.prototype.constructor = {}
console.log(StaticExample.staticProp) // "Hello"
Even after that, when I tried to access StaticExample.staticProp, it provides the correct value of Hello
Question 2: From where the staticProp fetched, even when the constructor where it was initially added is overwritten.
StaticExample is an object. A function object, but an object nonetheless.
You assign a new property to it: StaticExample.staticProp = "Hello".
StaticExample also happens to have a property prototype.
The property StaticExample.prototype.constructor points to StaticExample.
Now, you can obviously access StaticExample.staticProp, because it's simply a property of an object that you assigned.
You can also replace the value of StaticExample.prototype.constructor with something else; now StaticExample.prototype.constructor doesn't point to StaticExample anymore. But StaticExample is still StaticExample and it still has the property staticProp that you created on it. You didn't replace the StaticExample object in any way. What you did replace was StaticExample.prototype.constructor, which is a different property of a different object.
This was a question that originally came up because I was trying to document an ES2015 class with JSDoc, and to document the class's constructor function properly I needed to know the return value and its type, and I realized that I had no idea. In researching it I couldn't find the question being asked on Stack Overflow, so I dug around looking up the details of ES2015 classes, the new operator, and the constructor function. I have found what I think might be the answer, but thought it might be helpful to post the question on SO, along with what I found, and see if others can confirm or have better answers.
To demonstrate the question, suppose one has the following code:
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
var mySquare = new Rectangle(10, 10);
console.log(mySquare);//output: Object { height: 10, width: 10 }
One doesn't ever directly or explicitly call the constructor function, nor explicitly return anything from it, but it is clearly invoked and it must return something. So, what is the return value of the constructor function? And of what type is the return value?
To make things more difficult, one can't simply call the constructor and check the type of the return value, as I tried to do at first:
console.log(typeof mySquare.constructor(11, 11));//output: TypeError: class constructors must be invoked with |new|
console.log(typeof Rectangle.prototype.constructor(12, 12));//output: TypeError: class constructors must be invoked with |new|
According to MDN's reference on the new operator:
When the code new Foo(...) is executed, the following things happen:
A new object is created, inheriting from Foo.prototype.
The constructor function Foo is called with the specified arguments, and with this bound to the newly created object. new Foo is equivalent to new Foo(), i.e. if no argument list is specified, Foo is called without arguments.
The object returned by the constructor function becomes the result of the whole new expression. If the constructor function doesn't explicitly return an object, the object created in step 1 is used instead. (Normally constructors don't return a value, but they can choose to do so if they want to override the normal object creation process.)
(Emphasis mine.) So it seems that the return value of the constructor function is an object, more specifically an instance of the class.
Further research showed that the return value of the constructor can be overridden by explicitly returning any object from within the constructor function (though non-object return values will be ignored, in which case the default of the newly created object reference is used.) I could not find anything to indicate that ES2015 constructors are any different than constructors prior to ES2015 classes.
This Stack Overflow post was very helpful in researching the above, particularly this article it contained a link to, though since constructor did not appear in the code in either the question nor the article, with my limited understanding of constructors that I had going into researching this they did not seem at first to answer my question. Hopefully this may clarify for others in the same situation.
Edit: The veracity of MDN's information was called into question in comments, so I researched a more definitive source. The ECMA specification says of constructors:
A constructor is an object that supports the [[Construct]] internal method.
The [[Construct]] internal method is then defined as follows:
Signature: (a List of any, Object) → Object
Description: Creates an object. Invoked via the new or super operators. The first argument to the internal method is a list containing the arguments of the operator. The second argument is the object to which the new operator was initially applied. Objects that implement this internal method are called constructors. A function object is not necessarily a constructor and such non-constructor function objects do not have a [[Construct]] internal method.
The spec states that in describing signatures such as the one above, the following convention is used: "If an internal method explicitly returns a value, its parameter list is followed by the symbol “→” and the type name of the returned value."
So, to summarize, based on the ECMA specification as quoted above, yes, constructor functions definitively do in fact return objects.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why is it Object.defineProperty() rather than this.defineProperty() (for objects)?
I noticed that all the methods of a particular object can be called from the actual object instance, i.e., object.method(); or by passing the object to Object.method() as an argument. For example:
var a = ['one', 2, 3, 'four'];
a.reverse();
// OR
Array.reverse(a);
I seemed to get the same behaviour. I was wondering what the difference was and when one would be used over the other?
Object.method(o) looks on the Object object (Object is a real object in JavaScript) for a property called method and tries to call it passing in the variable o. During the call, this will be Object.
o.method() looks on the object referenced by the variable o for a property called method and tries to call it, not passing anything in. During the call, this will be o.
As you can see, they do quite different things.
I noticed that all the methods of a particular object can be called from the actual object instance...or by passing the object to Object.method() as an argument.
No, they cannot. Your example Array.reverse(a) fails on a standard implementation of Array because Array doesn't have a property called reverse and so it can't be called as a function. Edit: You note in the comments that it works in Firefox's scratchpad, and I just verified that. That means Firefox's SpiderMonkey JavaScript engine is applying a non-standard extension to Array which provides a static implementation of reverse. That's specific to Firefox's Array, not general to all objects. (If you make your own Foo, for instance, its prototype functions don't magically get added to Foo as well.)
The standard way to make the near-equivalent to a.reverse() would be via the prototype, like this:
Array.prototype.reverse.call(a);
That does work in standard engines. So let's look at what it does:
It gets the prototype property from Array.
It gets the reverse property from the object it got in #1.
It calls the function that property referenced using the Function#call feature of JavaScript function objects to make this be the argument you pass into call during the course of the function call.
When you create an array, the object gets an underlying prototype. That prototype is the object referenced by Array.prototype when the new array is created. So a has a reverse property because its underlying prototype has a reverse property.
Doing a.reverse() does this:
Gets the reverse property from the a object. Since (normally) a won't have its own property called reverse, standard JavaScript property lookup looks to a's underlying prototype. It finds the property there and uses its value.
Calls that function such that this is a within the call.
As you can see, the end result is the same provided that the underlying prototype of a and Array.prototype still refer to the same object. (It's possible for them not to, although in the case of Array or any other built-in, if someone replaced [as opposed to augmenting] Array.prototype, that would be a Bad Thing(tm).)
I am creating a few DOM elements dynamically like,
var anchorElement = jQuery('<a />',{text:property.text});
var liElement = jQuery('<li />',{"class":"navlink_"+i,id:"navlink_"+i});
anchorElement.on('click',property.fnctn);
liElement.append(anchorElement);
parentID.append(liElement);
Where property is a JSON object.
property.text is the text that I want to put into anchor element. (Works fine)
I want to attach a click event handler to that anchor element.
The function that needs to be bound to that element is specified in JSON and we can access it like
property.fnctn
The following line should bind the event handler to the anchor element.
anchorElement.on('click',property.fnctn);
This was not working so I tried converting it into string like,
anchorElement.on('click',property.fnctn.toString());
No Success...
When I click on this link, the error is logged in the console
The object has no method 'apply'.
What is the reason...???
I am able to get it working with a slight work around like
anchorElement.attr('onclick',property.fnctn+"()");
Above statement works, but I want to know why .on() API is not working.
Thanks :)
AÐitya.
Update:
Youve said that property.actfn is a string, "paySomeoneClick". It's best not to use strings for event handlers, use functions instead. If you want the function paySomeoneClick, defined in the string, to be called, and if that function is global, you can do this:
anchorElement.on('click',function(event) {
return window[property.fnctn](event);
});
That works because global functions are properties of the global object, which is available via window on browsers, and because of the bracketed notation described below.
If the function is on an object you have a reference to, then:
anchorElement.on('click',function(event) {
return theObject[property.fnctn](event);
});
That works because in JavaScript, you can access properties of objects in two ways: Dotted notation with a literal property name (foo.bar accesses the bar propety on foo) and bracketed notation with a string property name (foo["bar"]). They're equivalent, except of course in the bracketed notation, the string can be the result of an expression, including coming from a property value like property.fnctn.
But I would recommend stepping back and refactoring a bit so you're not passing function names around in strings. Sometimes it's the right answer, but in my experience, not often. :-)
Original answer:
(This assumed that property.fnctn was a function, not a string. But may be of some use to someone...)
The code
anchorElement.on('click',property.fnctn);
will attach the function to the event, but during the call to the function, this will refer to the DOM element, not to your property object.
To get around that, use jQuery's $.proxy:
anchorElement.on('click',$.proxy(property.fnctn, property));
...or ES5's Function#bind:
anchorElement.on('click',property.fnctn.bind(property));
...or a closure:
anchorElement.on('click',function(event) {
return property.fnctn(event);
});
More reading (on my blog):
Mythical methods
You must remember this
Closures are not complicated
I am having some trouble searching google and stackoverflow for the answer to what this piece of JavaScript code is doing:
obj['e'+type+fn]( window.event );
To me this looks like an array element with an argument/parameter:
array[index](argument);
However, I can only guess at what this is doing. Is this equivalent to:
array[index]=argument
Which is assigning an argument to the array element?
If anyone could provide a simple/generic example of what this is doing that would be great.
I am attempting to decipher John Resig's addEvent() implementation. I'm not really looking for an explanation of this implementation or example related to it, but more like a dumbed-down example like MDC has done for call which uses some imagined products.
obj['e'+type+fn]( window.event );
This is just a way of accessing a property of an object. For instance, if you have an object
a = {
name: 'someName'
age: 20
};
You can access name by using a.name or, as above a['name'].
The reason he is using the [] notation is so that he can build the key from multiple strings.
Thus if type=click and fn=foo he's accessing obj.eclickfoo. Or obj['eclickfoo']
This property of the object must be a method as he's invoking it using (); so again, he's saying:
obj.eclickfoo( window.event );
or equivalent
obj['eclickfoo']( window.event );
This is what it is doing:
From the array obj, it takes the function with index 'e'+type+fn. It then executes it passing window.event as a parameter.
Remember that () invokes a function, and [] extract a value from an array.
obj['e'+type+fn] returns a function type. This is then executed with window.event as a parameter.
obj['e'+type+fn]( window.event );
Arrays can indeed use the "obj[...]" notation, but so can any object in JavaScript. And in this case, Resig is adding the property to any object, specifically for DOM objects.
obj['aVar'] is equivalent to obj.aVar. The advantage of the former is that it can also work with keywords which are reserved in JavaScript to have special meaning (e.g., obj['var'] if you defined a property called "var" on an object) and allows property names to be accessed dynamically, as in your example. Since type is a variable, you could not do obj.type since that would be finding a property exactly named "type", not finding a property with the name equal to the value of the type variable.
Since objects (or arrays) can hold functions as data, you can also use the invocation operator (the matching parentheses) on a function found inside of an object or array, as is done here--the property is accessed (which is a previously stored "method" or function on an object) and then invoked with the window.event object as a single argument.
Functions also have a built-in toString method on their prototype (which will get called in cases like this where you are are concatenating to a string, and therefore must want a string, as long as you don't set your own toString method on your function, since functions are also objects in JavaScript!). Resig's code is taking advantage of this, to define a new property, somewhat haphazardly which is normally a bad idea, but in a way which is pretty unlikely to clash with other applications also adding such a property.
So if document.body is the obj and if the type variable is set to "click" and "fn" is set to function () {alert('boo!');}", it will actually name a property on the document.body object as "eloadfunction () {alert('boo!');}". As he explains, creating this property (and then invoking it inside his own anonymous function), allows the function to be called with the normal behavior of any "this" keyword used inside--this will refer to the parent object, in this case obj, not to a global (unless obj is the global--i.e., the window object).