Colleague showed me the next code, which blown my mind:
const x = Object.create(function() {});
// variant: const x = Object.create(Array);
console.log(x.call) // ƒ call() { [native code] }
console.log(typeof x.call) // "function"
console.log(x.call instanceof Function) // true
x.call() // Uncaught TypeError: x.call is not a function
I understand that x.call is prototyped from function, it's not own x's property:
x.hasOwnProperty('call') // false
But why x.call can't actually being executed? Is it something related to call keyword?
The core idea behind Object.create boils down to this:
function create(prt){
var noOP = function(){};
noOP.prototype = prt;
return new noOP;
}
So, the returned value is NOT a function, it is an object. To illustrate, I'll first store a function:
var u = function(){return 5}
Now I'll use Object.create on it:
var res = create(u);
Consoling it will give you >noOP {}, so it is a plain object. The problem starts from here:
res.hasOwnProperty("prototype") //false
So the newly created object has "prototype" but this is in fact inherited from u:
res.prototype === u.prototype //true
Similary, "call" is again inherited from u which in turn u inherits from its constructor's (Function) prototype:
res.call === u.call //true
res.call === Function.prototype.call //also true
And here is your problem, if you look at the EcmaScript implementation of call, it expects a this and this should be callable. Isolate call from res :
var x = res.call; //ƒ call() { [native code] }
Now I will "call" the call, we will pass 3 arguments, 1st for what to call, 2nd for setting this inside that callable, 3rd and so forth for arguments for the callable:
x.call(function(a){console.log("hey");console.log(a);console.log(this);},5,5)
//hey
//5
//Number {5}
Now try the same on your created object res either by res.call or x.call:
x.call(res,5,5) //TypeError: x.call is not a function
In the end, it boils down to returned object from Object.create not being callable.
Cause x is an object that inherits call from Function.prototype, however call is meant to be called on a function, therefore it fails if you try to execute it on a plain object.
Related
As we know, when we try to access an object's property it first check's if the object has its own property. If it does not find, it traverses the prototype and checks, and so on up the prototype chain.
Coming to the question, please check the below code snippet(http://jsbin.com/mabajidoti/edit?js,console)
function CT() {}
CT.prototype.myValue = 4;
var myObj = Object.create(CT);
console.log(myObj.myValue); //logs undefined
console.log(myObj.prototype.myValue) //logs 4
From the above snippet, the first console.log statement, myObj.myValue is returning undefined even though myValue is available in its prototype(2nd console.log statement)? Shouldn't it have traversed the prototype chain to fetch the myValue's value?
You seem to have confused Object.create() with calling a constructor function via the new operator.
If you'd said:
var myObj = new CT();
then your myObj would be linked to the CT.prototype and thus myObj.myValue would be 4.
But by using Object.create(CT) you've created a new object whose prototype is the CT function itself. So CT.prototype is not part of your new object's prototype chain. Note that CT.prototype isn't in CT's prototype chain, rather, it specifies the object that will be the prototype for things created with new CT().
A more correct use of Object.create() to allow access to a myValue property from the prototype would be:
var CT = {
myValue : 4
};
var myObj = Object.create(CT);
console.log(myObj.myValue); //logs 4
Or with your existing CT() function and CT.prototype you could say:
myObj = Object.create(CT.prototype);
prototype is instance variable, you can access prototype with obj.prototypeName when you create obj with new Obj()
first see Array
Array.forEach
// undefined
Array.prototype.forEach
// ƒ forEach() { [native code] }
new Array().forEach
// ƒ forEach() { [native code] }
[].forEach
// ƒ forEach() { [native code] }
see your CT class
function CT() {}
CT.prototype.myValue = 4;
var ct1 = new CT();
var ct2 = new CT();
ct1.myValue = 100;
console.log(ct1.myValue); //logs 100
console.log(ct2.myValue); //logs 4
If I return some value or object in constructor function, what will the var get?
function MyConstroctor()
{
//what in case when return 5;
//what in case when return someObject;
}
var n = new MyConstroctor();
what n will get in both cases?
Actually its a quiz question, what will be the answer?
What is returned from a custom object constructor?
a)The newly-instantiated object
b)undefined - constructors do not return values
c)Whatever is the return statement
d)Whatever is the return statement; the newly-instantiated object if no return statement
Short Answer
The constructor returns the this object.
function Car() {
this.num_wheels = 4;
}
// car = { num_wheels:4 };
var car = new Car();
Long Answer
By the Javascript spec, when a function is invoked with new, Javascript creates a new object, then sets the "constructor" property of that object to the function invoked, and finally assigns that object to the name this. You then have access to the this object from the body of the function.
Once the function body is executed, Javascript will return:
ANY object if the type of the returned value is object:
function Car(){
this.num_wheels = 4;
return { num_wheels:37 };
}
var car = new Car();
alert(car.num_wheels); // 37
The this object if the function has no return statement OR if the function returns a value of a type other than object:
function Car() {
this.num_wheels = 4;
return 'VROOM';
}
var car = new Car();
alert(car.num_wheels); // 4
alert(Car()); // No 'new', so the alert will show 'VROOM'
Basically if your constructor returns a primitive value, such as a string, number, boolean, null or undefined, (or you don't return anything which is equivalent to returning undefined), a newly created object that inherits from the constructor's prototype will be returned.
That's the object you have access with the this keyword inside the constructor when called with the new keyword.
For example:
function Test() {
return 5; // returning a primitive
}
var obj = new Test();
obj == 5; // false
obj instanceof Test; // true, it inherits from Test.prototype
Test.prototype.isPrototypeOf(obj); // true
But if the returned value is an object reference, that will be the returned value, e.g.:
function Test2() {
this.foo = ""; // the object referred by `this` will be lost...
return {foo: 'bar'};
}
var obj = new Test2();
obj.foo; // "bar"
If you are interested on the internals of the new operator, you can check the algorithm of the [[Construct]] internal operation, is the one responsible of creating the new object that inherits from the constructor's prototype, and to decide what to return:
13.2.2 [[Construct]]
When the [[Construct]] internal method for a Function object F is called with a possibly empty list of arguments, the following steps are taken:
Let obj be a newly created native ECMAScript object.
Set all the internal methods of obj as specified in 8.12.
Set the [[Class]] internal property of obj to "Object".
Set the [[Extensible]] internal property of obj to true.
Let proto be the value of calling the [[Get]] internal property of F with argument "prototype".
If Type(proto) is Object, set the[[Prototype]]` internal property of obj to proto.
If Type(proto) is not Object, set the [[Prototype]] internal property of obj to the standard built-in Object prototype object as described in 15.2.4.
Let result be the result of calling the [[Call]] internal property of F, providing obj as the this value and providing the argument list passed into [[Construct]] as args.
If Type(result) is Object then return result.
Return obj.
I found this great link:
JavaScript: Constructor Return Value
The second piece of magic eluded to above is the ability for a
constructor to return a specific, possibly pre-existing object, rather
than a reference to a new instance. This would allow you to manage the
number of actual instances yourself if needed; possibly for reasons of
limited resources or whatnot.
var g_deebee = new Deebee();
function Deebee() { return g_deebee; }
var db1 = new Deebee();
var db2 = new Deebee();
if (db1 != db2)
throw Error("JS constructor returned wrong object!");
else console.log('Equal');
It's as easy as it said in documentation (new operator) :
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.)
Trying to simplify the existing answers by providing discrete examples proving that:
Only constructors that return primitive or undefined implicitly create a new instance of themselves. Otherwise the exact object returned by the constructor is used as is.
Consider the following constructor that returns exactly what we pass to it. Check the usages:
//A constructor returning the passed value, or not returning at all.
function MyConstructor(obj){
if(obj!==undefined){
return obj;
}
//else do not call return
}
//no value passed (no value is returned from constructor)
console.log((new MyConstructor()) instanceof MyConstructor)
//true
//Primitive passed:
console.log((new MyConstructor(1)) instanceof MyConstructor)
//true
console.log((new MyConstructor(false)) instanceof MyConstructor)
//true
console.log((new MyConstructor("1")) instanceof MyConstructor)
//true
console.log((new MyConstructor(1.0)) instanceof MyConstructor)
//true
//Object passed
console.log((new MyConstructor(new Number(1))) instanceof MyConstructor)
//false
console.log((new MyConstructor({num:1})) instanceof MyConstructor)
//false
console.log((new MyConstructor([1])) instanceof MyConstructor)
//false
console.log((new MyConstructor(MyConstructor)) instanceof MyConstructor)
//false
//Same results if we use: MyConstructor.prototype.isPrototypeOf(new MyConstructor()) e.t.c..
The same rules as above apply also for class constructors. This means that, if the constructor does not return undefined or primitive, we can have the following, which might feel weird to people coming from java:
(new MyClass()) instanceof MyClass //false
Using the same constructor, check in practice how the instance is different when undefined or primitive is returned:
//As above
function MyConstructor(obj){
if(obj!==undefined){
return obj;
}
//else do not call return
}
//Same object passed (same instance to both variables)
let obj = {};
let a1 = new MyConstructor(obj)
let a2 = new MyConstructor(obj)
a1.x=1
a2.x=2
console.log(a1.x === a2.x, a1.x, a2.x)
//true 2 2
//undefined passed (different instance to each variable)
let b1 = new MyConstructor()
let b2 = new MyConstructor()
b1.x=1
b2.x=2
console.log(b1.x === b2.x, b1.x, b2.x)
//false 1 2
//Primitive passed (different instance to each variable)
let c1 = new MyConstructor(5)
let c2 = new MyConstructor(5)
c1.x=1
c2.x=2
console.log(c1.x === c2.x, c1.x, c2.x)
//false 1 2
Additional note: Sometimes a function could act as a constructor even if it is not called as a constructor:
function F(){
//If not called as a constructor, call as a constructor and return the result
if(!new.target){
return new F();
}
}
console.log(F() instanceof F)
//true
console.log(new F() instanceof F)
//true
You shouldn't return anything in a constructor. A constructor is used to initialize the object. In case you want to know what happens is that if you return 5 then n will simply be an empty object and if you return for example { a: 5 }, then n will have a property a=5.
To answer your specific question:
function MyConstructor()
{
return 5;
}
var n = new MyConstructor();
n is an object instance of MyConstructor.
function SomeObject(name) {
this.name = name;
this.shout = function() {
alert("Hello " + this.name)
}
}
function MyConstructor()
{
return new SomeObject("coure06");
}
var n = new MyConstructor();
n.shout();
n is an instance of SomeObject (call n.shout() to prove it)
To make this all absolutely clear...
1) If you return a primitive type, like a number or a string, it will be ignored.
2) Otherwise, you will pass back the object
Functions and constructors are exactly the same in JavaScript, but how you call them changes their behaviour. A quick example of this is below...
function AddTwoNumbers(first, second) {
return first + second;
}
var functionCall = AddTwoNumbers(5, 3);
alert(functionCall);// 8
var constructorCall = new AddTwoNumbers(5, 3);
alert(constructorCall);// object
This question already has answers here:
What does "return this" do within a javascript function?
(4 answers)
Closed 7 years ago.
Crockford's book JavaScript the Good Parts talks about a function for augmenting basic types. His function looks like this:
Function.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
}
I don't understand how / why the 'this' variable is used here. I've only used 'this' when calling that function with 'new', but this function is instead called like this:
Number.method('integer', function () {
return Math[this < 0 ? 'ceil' : 'floor'](this)
});
this refers to the Object which the function was referenced though when invoked.
var obj = {fn: function() {return this;}};
obj.fn(); // obj
var fn = obj.fn;
fn(); // window or null or error
fn.call(obj); // obj
fn.apply(obj); // obj
method is on Function.prototype, this means all Function instances inherit method and this inside method is expected to refer to the function instance which you're invoking it though, i.e.
Function.prototype.getThis = function () {return this;};
function hello() {}
hello.getThis(); // hello
// and consequently
hello.getThis().getThis().getThis().getThis().getThis(); // hello
Constructors are Functions too. Therefore all constructors inherit the method. The method example here hence means "Add a property name to the prototype inherited by instances of this (the constructor) and set the value of that property to func, then return the constructor so you can chain it"
function Foo() {}
Foo.method('bar', 'baz').method('fizz', 'buzz'); // Foo
var foo = new Foo();
foo.bar; // "baz", inherited from Foo.prototype
foo.fizz; // "buzz", inherited from Foo.prototype
this refers to its execution context. More precisely, it's used inside a function, and refers to the object that invoked it.
I've read the topic about "new" keyword in javascript (What is the 'new' keyword in JavaScript?). But, i'm still in the fog; let's talk about this example :
var foo = function() {
return {
setA: function(a) {
this.a = a;
},
readA: function() {
console.log(this.a);
}
};
};
And now what's about these two pieces of code :
One:
var bob1 = foo();
bob1.setA(10);
bob1.readA();
Two:
var bob2 = new foo();
bob2.setA(10);
bob2.readA();
I cannot see any differences at my level. So what is the gain to use the keyword "new" ?
If your function returns object directly, then you do not need an new operator.
The new keys does more than that.
Lets say
function Animal(kind, name) {
this.kind = kind;
this.name = name;
}
Animal.prototype.walk = function() {
console.log('Walking');
}
Then you are doing
var animal = new Animal();
Javascript engine will do following things
var o = Object.create(Animal.prototype)
Animal.apply(o, arguments);
return o;
Object.create will do the prototype inheritance of the prototype object of Animal function. So animal object will have its own properties and its inherited property.
i'm still in the fog about new; let's talk about this example :
var foo = function() {
return {
setA: function(a) {
this.a = a;
},
readA: function() {
console.log(this.a);
}
};
};
We shouldn't talk about this example. Whether or not we use new with this function does not make a difference, because of the way new works:
A new object is created, inheriting from foo.prototype.
The constructor function foo is called with the specified arguments and this bound
to
the newly created object.
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.)
Step 3 is the thing to look at here. You're creating and returning an object (the object literal), so that will become assigned to bob1. Usually, constructor functions do not return anything, and the new instance that is implicitly created in step1 (and available inside the function as this) becomes the result.
Both new foo() and foo() do only assign your object literal to the bob variable - no difference in the result. The instance created by the new is totally ignored by your code. It would be different in the following examples:
function foo() {
this.setA = function(a) {
this.a = a;
};
this.readA = function() {
console.log(this.a);
};
// return this; is implicit
}
var bob = new foo; // OK
var bob = foo(); // horrible error
If the constructor function foo returns an object, then new foo() is identical to calling the function foo() directly. We can prove this is so by examining the ECMAScript behavior for new:
Return the result of calling the [[Construct]] internal method on constructor [i.e., the constructor function]...
The [[Construct]] internal method of a function is a special wrapper for calling the function's [[Call]] internal method (which is just the function's normal behavior). Let's see the end of [[Construct]] to see how this wrapper behaves:
8) Let result be the result of calling the [[Call]] internal property of F [the function invoked by new], providing obj as the this value and providing the argument list passed into [[Construct]] as args.
9) If Type(result) is Object then return result.
10) Return obj.
In your case, your constructor function foo returns an object, so step 9 of [[Construct]] (and therefore, in turn, new foo()) returns that object. But we see in step 10 that [[Construct]] could return some other value called obj, which is equal to the this value inside the constructor. Let's rewind and see what that's all about:
1) Let obj be a newly created native ECMAScript object.
...
4) Let proto be the value of calling the [[Get]] internal property of F with argument "prototype".
5) If Type(proto) is Object, set the [[Prototype]] internal property of obj to proto.
Here we see the real power of new: if the constructor function does not return an object (and therefore the [[Construct]] operation launched by new is allowed to return obj), then prototypal inheritance takes place. The [[Prototype]] of obj (a.k.a. obj.__proto__) is set to the prototype property of the constructor method. This means that if foo doesn't return an object (and instead modifies this), and foo.prototype.someProp is set, then an instance returned from var instance = new foo() will have access to instance.someProp.
Thus, a different way to write your code might be:
var foo = function() { };
foo.prototype.setA = function(a) { this.a = a; };
foo.prototype.setA = function(a) { console.log(this.a); };
In this case, new foo() produces an object whose prototype chain includes foo.prototype, while foo() does not. This has the benefit of lower memory use: all foo instances here share common prototypal methods, instead of having each instance carry its own separate functions.
I am just curious whether I can include an object into function prototype chain. What I mean:
var test = function() { return 'a'; };
console.log(test.bind(this)); // return new bound function
// changing the prototype
// in console the prototype is really set as needed
// test => new object => function prototype => Object prototype
var F = function() {};
F.prototype = Function.prototype;
test.prototype = new F();
console.log(test.bind()); // this still works and returns new bound function
test.prototype.bind = function() {
return 'test';
};
console.log(test.bind()); // this does not work as expected -> returns new bound function instead of 'test'. When I do delete Function.prototype.bind, then console.log(test.bind) returns undefined
You have a function test. It is a instanceof Function, and inherits from Function.prototype so that you can call test.bind for example.
Then you set the "prototype" property of your function to an object inheriting from Function.prototype. That means that all instances of test will inherit from that object (and from Function.prototype):
var t = new test;
t instanceof test; // => true
t instanceof Function; // => true
Then you overwrite the test property on your custom prototype object. You do good to do so, because Function methods should only be called on functions (i.e. callable objects):
>>> Function.prototype.bind.call({})
Unhandled Error: Function.prototype.bind: this object not callable
In your tests with console.log you only apply the Function methods on your test function, not on instances of it. Good, because they'd fail. So, I can see no reason why any objects should inherit from Function - you can't construct functions that don't inherit directly from Function.