Javascript prototype , __proto__ - javascript

When I execute below java script code I get error at "v.dummy();" line , please let me know where am I doing wrong.
function Test()
{
}
Test.prototype.foo = function () {
console.log('foo');
}
var v = new Test();
v.foo();
v.__proto__ = function dummy() {
console.log('__proto__');
};
v.dummy(); // Uncaught TypeError: v.dummy is not a function

__proto__ is just a reference of an object
You can't make it equal a new function, but you can do it like this:
v.__proto__.foo = function dummy(){}

I don't know what you are trying to do, but:
1) when you assign function to a variable, you may omit the name (dummy) and use an anonymous function (without a name). Function name is useless in this case.
And if you do
var x = function y(){ ... }
you can call it like this: x(), not y()
2) __proto__ should be an object, not a function
usage of foo is correct, therefore it works.
You may want to consider reading a good JS book.

Related

Javascript: typeof says "function" but it can't be called as a function

I'm really puzzled with Javascript this time:
var x = Array.prototype.concat.call;
typeof x; // function
x(); // Uncaught TypeError: x is not a function
What on earth is going on here?
If it helps, I also noticed:
x([1,2],[3,4]) does not work either
toString also thinks it's a function:
Object.prototype.toString.call(x); // "[object Function]"
This also happens with Array.prototype.concat.apply.
When it is forced as an expression it also does not work:
(0, Array.prototype.concat.call)([1,2],[3,4]); // Same TypeError
Tested in Chrome and Node.
The error is misleading. x is a function, but it has lost the referenced function (concat), which throws an error
Running on firefox gives a more descriptive error
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Called_on_incompatible_type
What it's saying is that the call function has nothing its bound to.
In the same way that if you take an object like this:
const a = {
b: 2,
test() {
console.log('hi', this.b);
}
};
const c = a.test;
c();
You will get hi undefined as you've lost the relationship of the function to b.
You can fix this by either doing c.bind(a)() or c.call(a)
The call function behaves similarly. It is going to be the same for every function, and the pseudocode would look something like this:
class Function {
constructor(functionDefinition) {
this.functionDefinition = functionDefinition;
}
call(newThis, ...args) {
// take this.functionDefinition, and call it with `this` and `args`
}
}
Since you are extracting out the call function, it loses the function object it's associated with.
You can fix this by either binding concat to the function, or using call on call :-)
const a = []
const boundFn = a.concat.call.bind(a.concat)
console.log(boundFn([3], [1,2]));
// Or, you can use `call` to pass in the concat function
const callFn = a.concat.call;
console.log(callFn.call(a.concat, [4], [1,2]))

member function isn't a function error

With this code:
function thing(){
function majig(){
alert("done");
}
}
var mything = new thing();
mything.majig();
I'm getting this error:
TypeError: mything.majig is not a function
I've done javascript for some time, and I've done functions as part of functions and called them before. I know it has to be something simple I'm missing or forgetting, but various websearches (and poking around here) are getting me deeper theory answers, or examples that seem to indicate that this should work.
I know TypeError: foo is not a function usually means a syntax error. I've looked up examples, and it looks like I have the syntax right (I've tried a few variations with no success).
It's got to be some dumb simple mistake, but I'm just not catching it right now. What do I do in my function to make the mything.majig(); run properly?
You have declared a function in thing, but it's not attached to this at all. Try this:
function thing(){
this.majig = function() {
alert("done");
}
}
var mything = new thing();
mything.majig();
Alternately:
function thing() {
return {
majig: function() {
alert("done");
}
};
}
Or, better yet:
function thing() { }
thing.prototype.majig = function () {
alert('done');
}
The syntax is not what you think it means. It's not a member declaration. It's an inner function. Inner functions work just like local variables - they're only accessible in the scope of the outer function:
function foo () {
function bar () {}
bar(); // accessible here
}
bar(); // undefined here
If your function is a constructor, then to add a member function to the object that it constructs you'd add it to the constructor's prototype:
function Foo () {}
Foo.prototype.bar = function () {}; // bar is a member of object Foo
var f = new Foo();
f.bar(); // call member function
Objects in javascript are dynamic. They behave more like maps/hashes do in other languages. This means you can add a member function directly to an object instead of a constructor's prototype:
var f = {};
f.bar = function () {};
f.bar(); // call member function
Following the logic above, since this in a constructor refers to the object being constructed, you can also dynamically add a function to this. This is typically called "decoration" since it is effectively an ad-hoc version of the decorator design pattern:
function Foo () {
this.bar = function () {}
}
var f = new Foo();
f.bar();

How can I reference a `this` property within a method of `this`?

I append a services property to this:
function Client(){
this.services = {
'propertyName' : {}
};
and then append a method to this, in which I need to reference the services property of the instance of client:
function Client(){
this.services = {
'propertyName' : {}
};
this.someMethod = function () {
if (this.services['propertyName']) {
//do something
}
}
}
var clientName = new Client();
But this.services - line 6 is undefined. How can I use a property assigned to this in a method assigned to this? It seems like it should be possible because by the time that method is called by the constructor, the services property will exist for the object. Is this a language limitation? Is it possible? Should it be?
But this.services - line 6 is undefined.
That will depend entirely on how you call someMethod. If you call it like this:
clientName.someMethod();
...it'll be fine, because this within the call will be the object created by new Client that you've put the services property on. But in JavaScript, this is not a fixed thing with normal functions, it's set by how you call the function. So:
var f = clientName.someMethod;
f();
...would fail, because this wouldn't be the object you expect. (This isn't true of ES6's new "arrow" functions, which get this from where they're defined, not how they're called.)
You mostly see this when functions are used as callbacks:
doSomething(clientName.someMethod);
...because doSomething doesn't know what object to use as this.
You can fix it by using Function#bind:
doSomething(clientName.someMethod.bind(clientName));
or similarly:
var f = clientName.someMethod.bind(clientName);
f();
Function#bind creates a new function that, when called, will call the original with this set to the argument you give it.
Just to flesh out my ES6 comment above: In ES6, if you had:
function Client(){
this.services = {
'propertyName' : {}
};
this.someMethod = () => { // <== ES6 "arrow" function
if (this.services['propertyName']) {
//do something
}
}
}
...it wouldn't matter how you called someMethod, this would be what it is where that function was created. V. handy. :-)

Method vs Functions, and other questions

With respect to JS, what's the difference between the two? I know methods are associated with objects, but am confused what's the purpose of functions? How does the syntax of each of them differ?
Also, what's the difference between these 2 syntax'es:
var myFirstFunc = function(param) {
//Do something
};
and
function myFirstFunc(param) {
//Do something
};
Also, I saw somewhere that we need to do something like this before using a function:
obj.myFirstFunc = myFirstFunc;
obj.myFirstFunc("param");
Why is the first line required, and what does it do?
Sorry if these are basic questions, but I'm starting with JS and am confused.
EDIT: For the last bit of code, this is what I'm talking about:
// here we define our method using "this", before we even introduce bob
var setAge = function (newAge) {
this.age = newAge;
};
// now we make bob
var bob = new Object();
bob.age = 30;
// and down here we just use the method we already made
bob.setAge = setAge;
To answer your title question as to what is the difference between a 'function' and a 'method'.
It's semantics and has to do with what you are trying to express.
In JavaScript every function is an object. An object is a collection of key:value pairs. If a value is a primitive (number, string, boolean), or another object, the value is considered a property. If a value is a function, it is called a 'method'.
Within the scope of an object, a function is referred to as a method of that object. It is invoked from the object namespace MyObj.theMethod(). Since we said that a function is an object, a function within a function can be considered a method of that function.
You could say things like “I am going to use the save method of my object.” And "This save method accepts a function as a parameter.” But you generally wouldn't say that a function accepts a method as a parameter.
Btw, the book JavaScript Patterns by Stoyan Stefanov covers your questions in detail, and I highly recommend it if you really want to understand the language. Here's a quote from the book on this subject:
So it could happen that a function A, being an object, has properties and methods, one of which happens to be another function B. Then B can accept a function C as an argument and, when executed, can return another function D.
There is a slight difference -
Method : Method is a function when object is associated with it.
var obj = {
name : "John snow",
work : function someFun(paramA, paramB) {
// some code..
}
Function : When no object is associated with it , it comes to function.
function fun(param1, param2){
// some code...
}
Many answers are saying something along the lines that a method is what a function is called when it is defined on an object.
While this is often true in the way the word is used when people talk about JavaScript or object oriented programming in general (see here), it is worth noting that in ES6 the term method has taken on a very specific meaning (see section 14.3 Method Definitions of the specs).
Method Definitions
A method (in the strict sense) is a function that was defined through the concise method syntax in an object literal or as a class method in a class declaration / expression:
// In object literals:
const obj = {
method() {}
};
// In class declarations:
class MyClass {
method() {}
}
Method Specificities
This answer gives a good overview about the specificities of methods (in the strict sense), namely:
methods get assigned an internal [[HomeObject]] property which allows them to use super.
methods are not created with a prototype property and they don't have an internal [[Construct]] method which means that they cannot be called with new.
the name of a method does not become a binding in the method's scope.
Below are some examples illustrating how methods (in the strict sense) differ from functions defined on objects through function expressions:
Example 1
const obj = {
method() {
super.test; // All good!
},
ordinaryFunction: function ordinaryFunction() {
super.test; // SyntaxError: 'super' keyword unexpected here
}
};
Example 2
const obj = {
method() {},
ordinaryFunction: function ordinaryFunction() {}
};
console.log( obj.ordinaryFunction.hasOwnProperty( 'prototype' ) ); // true
console.log( obj.method.hasOwnProperty( 'prototype' ) ); // false
new obj.ordinaryFunction(); // All good !
new obj.method(); // TypeError: obj.method is not a constructor
Example 3
const obj = {
method() {
console.log( method );
},
ordinaryFunction: function ordinaryFunction() {
console.log( ordinaryFunction );
}
};
obj.ordinaryFunction() // All good!
obj.method() // ReferenceError: method is not defined
A method is a property of an object whose value is a function. Methods are called on objects in the following format: object.method().
//this is an object named developer
const developer = {
name: 'Andrew',
sayHello: function () {
console.log('Hi there!');
},
favoriteLanguage: function (language) {
console.log(`My favorite programming language is ${language}`);
}
};
// favoriteLanguage: and sayHello: and name: all of them are proprieties in the object named developer
now lets say you needed to call favoriteLanguage propriety witch is a function inside the object..
you call it this way
developer.favoriteLanguage('JavaScript');
// My favorite programming language is JavaScript'
so what we name this: developer.favoriteLanguage('JavaScript');
its not a function its not an object? what it is? its a method
Your first line, is creating an object that references a function. You would reference it like this:
myFirstFunc(param);
But you can pass it to another function since it will return the function like so:
function mySecondFunction(func_param){}
mySecondFunction(myFirstFunc);
The second line just creates a function called myFirstFunc which would be referenced like this:
myFirstFunc(param);
And is limited in scope depending on where it is declared, if it is declared outside of any other function it belongs to the global scope. However you can declare a function inside another function. The scope of that function is then limited to the function its declared inside of.
function functionOne(){
function functionTwo(){}; //only accessed via the functionOne scope!
}
Your final examples are creating instances of functions that are then referenced though an object parameter. So this:
function myFirstFunc(param){};
obj.myFirst = myFirstFunc(); //not right!
obj.myFirst = new myFirstFunc(); //right!
obj.myFirst('something here'); //now calling the function
Says that you have an object that references an instance of a function. The key here is that if the function changes the reference you stored in obj.myFirst will not be changed.
While #kevin is basically right there is only functions in JS you can create functions that are much more like methods then functions, take this for example:
function player(){
this.stats = {
health: 0,
mana: 0,
get : function(){
return this;
},
set : function( stats ){
this.health = stats.health;
this.mana = stats.mana;
}
}
You could then call player.stats.get() and it would return to you the value of heath, and mana. So I would consider get and set in this instance to be methods of the player.stats object.
A function executes a list of statements example:
function add() {
var a = 2;
var b = 3;
var c = a + b;
return c;
}
1) A method is a function that is applied to an object example:
var message = "Hello world!";
var x = message.toUpperCase(); // .toUpperCase() is a built in function
2) Creating a method using an object constructor. Once the method belongs to the object you can apply it to that object. example:
function Person(first, last, age, eyecolor) {
this.firstName = first;
this.lastName = last;
this.age = age;
this.eyeColor = eyecolor;
this.name = function() {return this.firstName + " " + this.lastName;};
}
document.getElementById("demo").innerHTML = person.fullName(); // using the
method
Definition of a method: A method is a property of an object that is a function. Methods are defined the way normal functions are defined, except that they have to be assigned as the property of an object.
var myFirstFunc = function(param) {
//Do something
};
and
function myFirstFunc(param) {
//Do something
};
are (almost) identical. The second is (usually) just shorthand. However, as this jsfiddle (http://jsfiddle.net/cu2Sy/) shows, function myFirstFunc will cause the function to be defined as soon as the enclosing scope is entered, whereas myFirstFunc = function will only create it once execution reaches that line.
As for methods, they have a this argument, which is the current object, so:
var obj = {};
obj.func = function( ) {
// here, "this" is obj
this.test = 2;
}
console.log( obj.test ); // undefined
obj.func( );
console.log( obj.test ); // 2
The exact syntax you showed is because you can also do this:
function abc( ) {
this.test = 2;
}
var obj = {};
obj.func = abc;
obj.func( ); // sets obj.test to 2
but you shouldn't without good reason.
ecma document
4.3.31method :
function that is the value of a property
NOTE When a function is called as a method of an object, the object is
passed to the function as its this value.
It is very clear: when you call a function if it implicitly has a this (to point an object) and if you can't call the function without an object, the function deserves to name as method.

Very basic Javascript constructors problem

In the following JavaScript code main() is called.
My question is why the second constructor is called rather than the first one ?
What am I missing here ?
Thanks !!
function AllInputs() {
alert("cons 1");
this.radioInputs = [];
alert(this);
}
function AllInputs(radioElement) {
alert("cons 2");
this.radioInputs = [radioElement];
alert(this);
}
AllInputs.prototype.toString = function() {
return "[object AllInputs: radioInputs: " + this.radioInputs.length + "]";
}
function main() {
var result = new AllInputs();
}
Javascript does not support overloaded functions.
When you define the same function twice, the second definition replaces the first one.
Instead, you should make a single function, and check arguments.length to see how many arguments were passed.
For example:
function AllInputs(radioElement) {
this.radioInputs = arguments.length ? [radioElement] : [];
alert(this);
}
In JavaScript, the last definition of an identifier is used:
function foo() { return "bar"; }
var foo = "foo";
alert(foo);
In that case, foo was a variable with the value "foo". Had foo been a function, it would have simply said that foo was a function. If you don't believe it, try using alert(foo()) instead of just alert(foo). You'll most likely get an error in your console log with no visible output like you had with alert(foo) (the variable...not the function call).
function foo() { ... }
is really just shorthand for
var foo = function () { ... }
Hence, the second time you're declaring the function, you're overwriting the variable AllInputs with a different function. There ain't no such thing as two functions with the same name in Javascript, since all functions are really variables.

Categories