bind method creates a new function that when called has its this keyword set to the provided value.
var obj = {
a: 0,
b() {
console.log(this.a);
}
}
obj.b() // -> 0
var functionBound = obj.b.bind(obj)
functionBound() // -> 0
functionBound.bind(null)() // -> 0 AND I expect an error here
Clearly, I cannot rebind a function has already been rebound. However, I could not find any documentation on this behavior.
Quote from "Bind more arguments of an already bound function in Javascript"
Once you bound an object to a function with bind, you cannot override it. It's clearly written in the specs, as you can see in MDN documentation:
The bind() function creates a new function (a bound function) with the same function body (internal call property in ECMAScript 5 terms) as the function it is being called on (the bound function's target function) with the this value bound to the first argument of bind(), which cannot be overridden.
I could not find these in MDN documentation. I did an exact full-text search on the quote above on Google and seems the SO answer above is the only source for this behavior. I also try to find an answer in the language spec with no luck.
My question is do you know this behavior and where can I find any official documentation on these?
This may not directly answer the question about getting a officially documented specification validating this behavior, but we can base our conclusions on the source code provided in MDN, specifically in the documentation for Function.prototype.bind(), under section Polyfill, where they provide an example of how a polyfill bind function would look like.
if (!Function.prototype.bind) {
Function.prototype.bind = function(oThis) {
if (typeof this !== 'function') {
// closest thing possible to the ECMAScript 5
// internal IsCallable function
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function() {},
fBound = function() {
return fToBind.apply(this instanceof fNOP
? this
: oThis,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
if (this.prototype) {
// Function.prototype doesn't have a prototype property
fNOP.prototype = this.prototype;
}
fBound.prototype = new fNOP();
return fBound;
};
}
We can see that the oThis parameter is used in the closure fBound which is the one ultimately returned by the bind function.
This means that when you invoke the bind function, you get a closure function in return which, when invoked, accesses the oThis free variable provided as parameter in the original invocation of bind.
As such, it doesn't matter how many more times you rebind the bound fBound function, this function is already bound forever to the original context oThis within its closure.
The MDN documentation also points to Raynos bind implementation for further reference, which seems to correspond to this example as well.
The problem is that Function.prototype.bind returns a NEW function instead of the same. Calling a bound function with a different this-argument has no effect, because the bound function already knows which value to use as the this-argument.
You could use this for binding your functions:
Function.boundOriginProp = Symbol()
Function.prototype.bindDynamic = thisArg => {
let origin = this[Function.bindOriginProp] || this
let bound = (...args) => origin.call(thisArg, ...args)
bound[Function.bindOriginProp] = origin
return bound
}
So you can rebind functions that have already been bound like this:
let obj1 = { value: 1 }
let obj2 = { value: 2 }
function example() {
console.log(this.value)
}
let fn1 = example.bindDynamic(obj1)
fn1() // -> 1
let fn2 = fn1.bindDynamic(obj2)
fn2() // -> 2
let fn3 = fn1.bindDynamic(null)
fn3() // -> undefined
I hope this can help you ;)
The bind method wraps the original function and creates a new Bounded Function.
Actually, a function which wraps the original function keeping the same body of the original function.
This is the definition in the MDN website:
The bind() function creates a new bound function (BF). A BF is an
exotic function object (a term from ECMAScript 2015) that wraps the
original function object. Calling a BF generally results in the
execution of its wrapped function.
So, every time you call .bind, you create a new function passing the context as first parameter and the args as rest of parameters, but keeping the body of the first definition.
You can also override the initial body, and bind the function again.
At the same time, you can also take a previously bounded function and bind it again to a new function.
In the following example, you should see the expected behavior:
var printer = function(a) {
console.log(a);
};
var printer1 = printer.bind(null, 1);
var printer2 = printer.bind(null, 2);
var printer3 = printer.bind(null, 3);
printer1();
printer2();
printer3();
printer = function(a) {
console.log("I am a new " + a);
};
var printer4 = printer.bind(null, 4);
printer4();
var newPrinter = function() {
console.log('I am a new printer!');
}
printer4 = newPrinter.bind(null);
printer4();
ES6 allows to extend special objects. So it's possible to inherit from the function. Such object can be called as a function, but how can I implement the logic for such call?
class Smth extends Function {
constructor (x) {
// What should be done here
super();
}
}
(new Smth(256))() // to get 256 at this call?
Any method of class gets reference to the class instance via this. But when it is called as a function, this refers to window. How can I get the reference to the class instance when it is called as a function?
PS: Same question in Russian.
The super call will invoke the Function constructor, which expects a code string. If you want to access your instance data, you could just hardcode it:
class Smth extends Function {
constructor(x) {
super("return "+JSON.stringify(x)+";");
}
}
but that's not really satisfying. We want to use a closure.
Having the returned function be a closure that can access your instance variables is possible, but not easy. The good thing is that you don't have to call super if you don't want to - you still can return arbitrary objects from your ES6 class constructors. In this case, we'd do
class Smth extends Function {
constructor(x) {
// refer to `smth` instead of `this`
function smth() { return x; };
Object.setPrototypeOf(smth, Smth.prototype);
return smth;
}
}
But we can do even better, and abstract this thing out of Smth:
class ExtensibleFunction extends Function {
constructor(f) {
return Object.setPrototypeOf(f, new.target.prototype);
}
}
class Smth extends ExtensibleFunction {
constructor(x) {
super(function() { return x; }); // closure
// console.log(this); // function() { return x; }
// console.log(this.prototype); // {constructor: …}
}
}
class Anth extends ExtensibleFunction {
constructor(x) {
super(() => { return this.x; }); // arrow function, no prototype object created
this.x = x;
}
}
class Evth extends ExtensibleFunction {
constructor(x) {
super(function f() { return f.x; }); // named function
this.x = x;
}
}
Admittedly, this creates an additional level of indirection in the inheritance chain, but that's not necessarily a bad thing (you can extend it instead of the native Function). If you want to avoid it, use
function ExtensibleFunction(f) {
return Object.setPrototypeOf(f, new.target.prototype);
}
ExtensibleFunction.prototype = Function.prototype;
but notice that Smth will not dynamically inherit static Function properties.
This is an approach to creating callable objects that correctly reference their object members, and maintain correct inheritance,
without messing with prototypes.
Simply:
class ExFunc extends Function {
constructor() {
super('...args', 'return this.__self__.__call__(...args)')
var self = this.bind(this)
this.__self__ = self
return self
}
// Example `__call__` method.
__call__(a, b, c) {
return [a, b, c];
}
}
Extend this class and add a __call__ method, more below...
An explanation in code and comments:
// This is an approach to creating callable objects
// that correctly reference their own object and object members,
// without messing with prototypes.
// A Class that extends Function so we can create
// objects that also behave like functions, i.e. callable objects.
class ExFunc extends Function {
constructor() {
super('...args', 'return this.__self__.__call__(...args)');
// Here we create a function dynamically using `super`, which calls
// the `Function` constructor which we are inheriting from. Our aim is to create
// a `Function` object that, when called, will pass the call along to an internal
// method `__call__`, to appear as though the object is callable. Our problem is
// that the code inside our function can't find the `__call__` method, because it
// has no reference to itself, the `this` object we just created.
// The `this` reference inside a function is called its context. We need to give
// our new `Function` object a `this` context of itself, so that it can access
// the `__call__` method and any other properties/methods attached to it.
// We can do this with `bind`:
var self = this.bind(this);
// We've wrapped our function object `this` in a bound function object, that
// provides a fixed context to the function, in this case itself.
this.__self__ = self;
// Now we have a new wrinkle, our function has a context of our `this` object but
// we are going to return the bound function from our constructor instead of the
// original `this`, so that it is callable. But the bound function is a wrapper
// around our original `this`, so anything we add to it won't be seen by the
// code running inside our function. An easy fix is to add a reference to the
// new `this` stored in `self` to the old `this` as `__self__`. Now our functions
// context can find the bound version of itself by following `this.__self__`.
self.person = 'Hank'
return self;
}
// An example property to demonstrate member access.
get venture() {
return this.person;
}
// Override this method in subclasses of ExFunc to take whatever arguments
// you want and perform whatever logic you like. It will be called whenever
// you use the obj as a function.
__call__(a, b, c) {
return [this.venture, a, b, c];
}
}
// A subclass of ExFunc with an overridden __call__ method.
class DaFunc extends ExFunc {
constructor() {
super()
this.a = 'a1'
this.b = 'b2'
this.person = 'Dean'
}
ab() {
return this.a + this.b
}
__call__(ans) {
return [this.ab(), this.venture, ans];
}
}
// Create objects from ExFunc and its subclass.
var callable1 = new ExFunc();
var callable2 = new DaFunc();
// Inheritance is correctly maintained.
console.log('\nInheritance maintained:');
console.log(callable2 instanceof Function); // true
console.log(callable2 instanceof ExFunc); // true
console.log(callable2 instanceof DaFunc); // true
// Test ExFunc and its subclass objects by calling them like functions.
console.log('\nCallable objects:');
console.log( callable1(1, 2, 3) ); // [ 'Hank', 1, 2, 3 ]
console.log( callable2(42) ); // [ 'a1b2', Dean', 42 ]
// Test property and method access
console.log(callable2.a, callable2.b, callable2.ab())
View on repl.it
Further explanation of bind:
function.bind() works much like function.call(), and they share a similar method signature:
fn.call(this, arg1, arg2, arg3, ...); more on mdn
fn.bind(this, arg1, arg2, arg3, ...); more on mdn
In both the first argument redefines the this context inside the function. Additional arguments can also be bound to a value.
But where call immediately calls the function with the bound values, bind returns an "exotic" function object that transparently wraps the original, with this and any arguments preset.
So when you define a function then bind some of its arguments:
var foo = function(a, b) {
console.log(this);
return a * b;
}
foo = foo.bind(['hello'], 2);
You call the bound function with only the remaining arguments, its context is preset, in this case to ['hello'].
// We pass in arg `b` only because arg `a` is already set.
foo(2); // returns 4, logs `['hello']`
You can wrap the Smth instance in a Proxy with an apply (and maybe construct) trap:
class Smth extends Function {
constructor (x) {
super();
return new Proxy(this, {
apply: function(target, thisArg, argumentsList) {
return x;
}
});
}
}
new Smth(256)(); // 256
Update:
Unfortunately this doesn't quite work because it's now returning a function object instead of a class, so it seems this actually can't be done without modifying the prototype. Lame.
Basically the problem is there is no way of setting the this value for the Function constructor. The only way to really do this would be to use the .bind method afterwards, however this is not very Class-friendly.
We could do this in a helper base class, however this does does not become available until after the initial super call, so it's a bit tricky.
Working Example:
'use strict';
class ClassFunction extends function() {
const func = Function.apply(null, arguments);
let bound;
return function() {
if (!bound) {
bound = arguments[0];
return;
}
return func.apply(bound, arguments);
}
} {
constructor(...args) {
(super(...args))(this);
}
}
class Smth extends ClassFunction {
constructor(x) {
super('return this.x');
this.x = x;
}
}
console.log((new Smth(90))());
(Example requires modern browser or node --harmony.)
Basically the base function ClassFunction extends will wrap the Function constructor call with a custom function which is similar to .bind, but allows binding later, on the first call. Then in the ClassFunction constructor itself, it calls the returned function from super which is now the bound function, passing this to finish setting up the custom bind function.
(super(...))(this);
This is all quite a bit complicated, but it does avoid mutating the prototype, which is considered bad-form for optimization reasons and can generate warnings in browser consoles.
I took the advice from Bergi's answer and wrapped it into an NPM module.
var CallableInstance = require('callable-instance');
class ExampleClass extends CallableInstance {
constructor() {
// CallableInstance accepts the name of the property to use as the callable
// method.
super('instanceMethod');
}
instanceMethod() {
console.log("instanceMethod called!");
}
}
var test = new ExampleClass();
// Invoke the method normally
test.instanceMethod();
// Call the instance itself, redirects to instanceMethod
test();
// The instance is actually a closure bound to itself and can be used like a
// normal function.
test.apply(null, [ 1, 2, 3 ]);
This is the solution I've worked out that serves all my needs of extending functions and has served me quite well. The benefits of this technique are:
When extending ExtensibleFunction, the code is idiomatic of extending any ES6 class (no, mucking about with pretend constructors or proxies).
The prototype chain is retained through all subclasses, and instanceof / .constructor return the expected values.
.bind() .apply() and .call() all function as expected. This is done by overriding these methods to alter the context of the "inner" function as opposed to the ExtensibleFunction (or it's subclass') instance.
.bind() returns a new instance of the functions constructor (be it ExtensibleFunction or a subclass). It uses Object.assign() to ensure the properties stored on the bound function are consistent with those of the originating function.
Closures are honored, and arrow functions continue to maintain the proper context.
The "inner" function is stored via a Symbol, which can be obfuscated by modules or an IIFE (or any other common technique of privatizing references).
And without further ado, the code:
// The Symbol that becomes the key to the "inner" function
const EFN_KEY = Symbol('ExtensibleFunctionKey');
// Here it is, the `ExtensibleFunction`!!!
class ExtensibleFunction extends Function {
// Just pass in your function.
constructor (fn) {
// This essentially calls Function() making this function look like:
// `function (EFN_KEY, ...args) { return this[EFN_KEY](...args); }`
// `EFN_KEY` is passed in because this function will escape the closure
super('EFN_KEY, ...args','return this[EFN_KEY](...args)');
// Create a new function from `this` that binds to `this` as the context
// and `EFN_KEY` as the first argument.
let ret = Function.prototype.bind.apply(this, [this, EFN_KEY]);
// For both the original and bound funcitons, we need to set the `[EFN_KEY]`
// property to the "inner" function. This is done with a getter to avoid
// potential overwrites/enumeration
Object.defineProperty(this, EFN_KEY, {get: ()=>fn});
Object.defineProperty(ret, EFN_KEY, {get: ()=>fn});
// Return the bound function
return ret;
}
// We'll make `bind()` work just like it does normally
bind (...args) {
// We don't want to bind `this` because `this` doesn't have the execution context
// It's the "inner" function that has the execution context.
let fn = this[EFN_KEY].bind(...args);
// Now we want to return a new instance of `this.constructor` with the newly bound
// "inner" function. We also use `Object.assign` so the instance properties of `this`
// are copied to the bound function.
return Object.assign(new this.constructor(fn), this);
}
// Pretty much the same as `bind()`
apply (...args) {
// Self explanatory
return this[EFN_KEY].apply(...args);
}
// Definitely the same as `apply()`
call (...args) {
return this[EFN_KEY].call(...args);
}
}
/**
* Below is just a bunch of code that tests many scenarios.
* If you run this snippet and check your console (provided all ES6 features
* and console.table are available in your browser [Chrome, Firefox?, Edge?])
* you should get a fancy printout of the test results.
*/
// Just a couple constants so I don't have to type my strings out twice (or thrice).
const CONSTRUCTED_PROPERTY_VALUE = `Hi, I'm a property set during construction`;
const ADDITIONAL_PROPERTY_VALUE = `Hi, I'm a property added after construction`;
// Lets extend our `ExtensibleFunction` into an `ExtendedFunction`
class ExtendedFunction extends ExtensibleFunction {
constructor (fn, ...args) {
// Just use `super()` like any other class
// You don't need to pass ...args here, but if you used them
// in the super class, you might want to.
super(fn, ...args);
// Just use `this` like any other class. No more messing with fake return values!
let [constructedPropertyValue, ...rest] = args;
this.constructedProperty = constructedPropertyValue;
}
}
// An instance of the extended function that can test both context and arguments
// It would work with arrow functions as well, but that would make testing `this` impossible.
// We pass in CONSTRUCTED_PROPERTY_VALUE just to prove that arguments can be passed
// into the constructor and used as normal
let fn = new ExtendedFunction(function (x) {
// Add `this.y` to `x`
// If either value isn't a number, coax it to one, else it's `0`
return (this.y>>0) + (x>>0)
}, CONSTRUCTED_PROPERTY_VALUE);
// Add an additional property outside of the constructor
// to see if it works as expected
fn.additionalProperty = ADDITIONAL_PROPERTY_VALUE;
// Queue up my tests in a handy array of functions
// All of these should return true if it works
let tests = [
()=> fn instanceof Function, // true
()=> fn instanceof ExtensibleFunction, // true
()=> fn instanceof ExtendedFunction, // true
()=> fn.bind() instanceof Function, // true
()=> fn.bind() instanceof ExtensibleFunction, // true
()=> fn.bind() instanceof ExtendedFunction, // true
()=> fn.constructedProperty == CONSTRUCTED_PROPERTY_VALUE, // true
()=> fn.additionalProperty == ADDITIONAL_PROPERTY_VALUE, // true
()=> fn.constructor == ExtendedFunction, // true
()=> fn.constructedProperty == fn.bind().constructedProperty, // true
()=> fn.additionalProperty == fn.bind().additionalProperty, // true
()=> fn() == 0, // true
()=> fn(10) == 10, // true
()=> fn.apply({y:10}, [10]) == 20, // true
()=> fn.call({y:10}, 20) == 30, // true
()=> fn.bind({y:30})(10) == 40, // true
];
// Turn the tests / results into a printable object
let table = tests.map((test)=>(
{test: test+'', result: test()}
));
// Print the test and result in a fancy table in the console.
// F12 much?
console.table(table);
Edit
Since I was in the mood, I figured I'd publish a package for this on npm.
Firstly I came to solution with arguments.callee, but it was awful.
I expected it to break in global strict mode, but seems like it works even there.
class Smth extends Function {
constructor (x) {
super('return arguments.callee.x');
this.x = x;
}
}
(new Smth(90))()
It was a bad way because of using arguments.callee, passing the code as a string and forcing its execution in non-strict mode. But than idea to override apply appeared.
var global = (1,eval)("this");
class Smth extends Function {
constructor(x) {
super('return arguments.callee.apply(this, arguments)');
this.x = x;
}
apply(me, [y]) {
me = me !== global && me || this;
return me.x + y;
}
}
And the test, showing I'm able to run this as function in different ways:
var f = new Smth(100);
[
f instanceof Smth,
f(1),
f.call(f, 2),
f.apply(f, [3]),
f.call(null, 4),
f.apply(null, [5]),
Function.prototype.apply.call(f, f, [6]),
Function.prototype.apply.call(f, null, [7]),
f.bind(f)(8),
f.bind(null)(9),
(new Smth(200)).call(new Smth(300), 1),
(new Smth(200)).apply(new Smth(300), [2]),
isNaN(f.apply(window, [1])) === isNaN(f.call(window, 1)),
isNaN(f.apply(window, [1])) === isNaN(Function.prototype.apply.call(f, window, [1])),
] == "true,101,102,103,104,105,106,107,108,109,301,302,true,true"
Version with
super('return arguments.callee.apply(arguments.callee, arguments)');
in fact contains bind functionality:
(new Smth(200)).call(new Smth(300), 1) === 201
Version with
super('return arguments.callee.apply(this===(1,eval)("this") ? null : this, arguments)');
...
me = me || this;
makes call and apply on window inconsistent:
isNaN(f.apply(window, [1])) === isNaN(f.call(window, 1)),
isNaN(f.apply(window, [1])) === isNaN(Function.prototype.apply.call(f, window, [1])),
so the check should be moved into apply:
super('return arguments.callee.apply(this, arguments)');
...
me = me !== global && me || this;
Generalizing Oriol's answer:
class Smth extends Function {
constructor(x) {
super();
this.x = x;
return new Proxy(this, {
apply: (target, that, args) => target.__call__(...args)
});
}
__call__(v) {
return this.x * v;
}
}
There is a simple solution which takes advantage of JavaScript's functional capabilities: Pass the "logic" as a function-argument to the constructor of your class, assign the methods of that class to that function, then return that function from the constructor as the result:
class Funk
{
constructor (f)
{ let proto = Funk.prototype;
let methodNames = Object.getOwnPropertyNames (proto);
methodNames.map (k => f[k] = this[k]);
return f;
}
methodX () {return 3}
}
let myFunk = new Funk (x => x + 1);
let two = myFunk(1); // == 2
let three = myFunk.methodX(); // == 3
The above was tested on Node.js 8.
A shortcoming of the example above is it does not support methods inherited from the superclass-chain. To support that, simply replace "Object . getOwnPropertyNames(...)" with something that returns also the names of inherited methods. How to do that I believe is explained in some other question-answer on Stack Overflow :-). BTW. It would be nice if ES7 added a method to produce inherited methods' names as well ;-).
If you need to support inherited methods one possibility is adding a static method to the above class which returns all inherited and local method names. Then call that from the constructor. If you then extend that class Funk, you get that static method inherited along as well.
Having read this article and all the answers here, I finally found a satisfying answer in an older thread.
Here's an example:
class Hey {
constructor() {
function hey() {
return "hey";
}
this.value = "yo";
Object.assign(hey, this);
Object.setPrototypeOf(hey, Object.getPrototypeOf(this));
return hey;
}
yo() {
return this.value;
}
}
const hey = new Hey();
console.log(hey()); // it's callable 👍
console.log(hey.yo()); // methods are correctly bound to `this` 👍
console.log(hey instanceof Hey); // it type-checks 👍
Inheritance works too:
class HeyHey extends Hey {
constructor() {
super();
}
yoyo() {
return this.value + "!";
}
}
const lol = new HeyHey();
console.log(lol()); // it's callable 👍
console.log(lol.yo()); // inherited methods are correctly bound to `this` 👍
console.log(lol.yoyo()); // new methods are correctly bound to `this` as well 👍
console.log(lol instanceof Hey); // it type-checks for the super class 👍
console.log(lol instanceof HeyHey); // it type-checks for the derived class 👍
You can run the example here to see for yourself.
This approach:
correctly binds methods to this
is type-safe (can be type-checked using instanceof)
correctly supports inheritance (correctly binds and type-checks derived classes)
doesn't rely on any features newer than class - getPrototypeOf and setPrototypeOf were widely available some years before class
doesn't rely on the Function constructor (avoids parsing source code at run-time)
doesn't rely on Proxy (which isn't great for performance)
All in all, this approach is definitely simpler and easier to implement, and it should perform better as well.
(In theory - please feel free to benchmark this and post your results.)
Came up with a solution that works without using Object.setPrototypeOf since MDN has big red warning signs around that. Can run the example JSFiddle here. One limitation I can't figure out is how to get access to the this context at call time of the produced function within the arbitrary execute.
class ExtendedFunction extends Function {
// Arbitrary private properties
#foo
#baz() { return this.#foo + 'qux' }
// The thing that happens when you call your extended function
// context is optional if you want access to the `this`
// provides to your extended function at call time
#execute() {
// Arbitrary code that can call anything in closure here
return this.#baz()
}
constructor(a) {
// Set `this` to simple wrapper function
// that takes another function and returns its value
// Use super we get an instance of Function and ExtendedFucntion
super('execute', 'return execute()')
this.#foo = a
// Bind our arbitrary function to the current `this`
// allowing it to access private properties even when passed around
const boundExecute = this.#execute.bind(this)
// Bind the simple wrapper and the boundExecute together and return that
// When called our extended function will do whatever is in #execute
var self = this.bind(null, boundExecute)
return self
}
}
const a = new ExtendedFunction(256)
console.log(a instanceof Function) // true
console.log(a instanceof ExtendedFunction) // true
console.log(a()) // 256qux
A little late but let me leave this here.
Recently I had to discover a way to subclass Function in order to turn normal functions into Threadable / Promisified functions without messing with the Function.prototype. I think this particular necessity forms a very reasonable basis to this question on how and why one can use class abstraction to extend Function.
So the idea is, we create a Threadable class of which the member functions are threadable. By this I mean, any normal function can easily be made Threadable and when spawned runs on a seperate thread and gives us a promise to be resolved or rejected depending on the outcome of the worker operation. However you should still be able to invoke it syncronously if need be.
class Threadable extends Function {
// just use super() to wrap the given f function with a transparent function layer
constructor(f){
super("...as",`return ${f.toString()}.apply(this,as)`);
}
// spawn is the only method of the Threadable class.
// Returns a promise and runs callee function on a separate thread.
spawn(...as){
var code = `self.onmessage = m => self.postMessage((${this.toString()}).apply(self,m.data));`,
blob = new Blob([code], {type: "text/javascript"}),
wrkr = new Worker(window.URL.createObjectURL(blob));
return new Promise( (v,x) => ( wrkr.onmessage = m => (v(m.data), wrkr.terminate())
, wrkr.onerror = e => (x(e.message), wrkr.terminate())
, wrkr.postMessage(as)
)
);
}
}
function add(...ns) {
return ns.reduce((a,b) => a+b);
}
var addT = new Threadable(add);
addT.spawn(1,2,3,4)
.then(m => console.log(`Promisified thread returned ${m}`));
console.log(`Synchronous invocation of addT returned ${addT(1,2,3,4,5)}`);
I am learning javascript and would love help understanding the snippet of code.
From Object.DefineProperties definition, the first parameter is an object. Is MyObjectConstructor a declaration or an object. With a constructor function I would expect to call new to make it an object.
This is what is confusing me. Or as I read in Javascript functions are objects so do I treat it as an object and the this property is where all staticProps and instanceProps are added to?
var _prototypeProperties = function (child, staticProps, instanceProps) {
if (staticProps){
Object.defineProperties(child, staticProps)
};
if (instanceProps) {
Object.defineProperties(child.prototype, instanceProps);
}
};
function myFunction() {
function MyObjectConstructor(element) {
this.element = element;
this.initialized = false;
}
_prototypeProperties(MyObjectConstructor, {...}, {...});
}
Yes, (constructor) functions are objects as well in javascript, and you can add properties directly to them.
The _prototypeProperties function in your example snippet does put the staticProperties on the constructor, so that they could be accessed as MyObjectConstructor.myStaticProperty. It also does put instanceProps (better: "class properties", "prototype properties") on the MyObjectConstructor.prototype object, from where they are inherited by instances: (new MyObjectConstructor).myPrototypeProperty. Lastly, your MyObjectConstructor does put "real" (own) properties on the instances, specifically (new MyObjectConstructor).element and .initialised.
In JavaScript, once defined, the resulting functions act identically:
function Hat() { }
var Hat = function() { }
Conventionally the first is used to create objects (usually with new) and the second is used as a regular method.
The new operator, when preceding a function gets kinda weird. Using the new operator will:
create a new Object "it"
set the function being called as "it"s prototype
binds "it" to this within the function
overrides the return value of the function with "it". This overrides both explicit returns and implicit returns of undefined.
For example:
// first define Hat function
function Hat() { this.color = 'red' }
// calling with `new` implicitly returns a new object bound to the function
new Hat()
// > Hat { color: "red" }
// invoking without `new` implicitly returns `unefined`,
// but `this` points to Hat's parent object.
// If running in the browser, Hat's parent object would be `window`
// so now Window.color is set to "red"
Hat()
//> undefined
Window.color
//> "red"
Be careful with new, because the new object will be returned instead of any explicit returns.
var color = function() { return "blue" }
color()
//> "blue"
new color()
//> color {}
JavaScript is prototypal by nature. The new operator reflects neither prototypical nor classical inheritance. I avoid it when possible, although many popular libraries use it.
I recommend reading through Crockford's explanation of JavaScript's prototypal inheritance: http://javascript.crockford.com/prototypal.html
Its terse, but if you understand his 10 lines of demo code you'll be good.
Play with bind, call and apply, and different scoping contexts too. After understanding scoping and the prototypal nature, the rest is just syntax.
first : the function is the first type object in the javascript . it means you can deliver the function as value . for example :
function test(){
return function(){
console.log('function');
}
}
test()();
you return the function as return an object , function can be assigned and the function another kind of value !
var test = function(i) {
// body...
return i;
}
test('123');
a character string 'test' refer to a Anonymous function , you can understand that you transmit a function to a character string .
second : if you use new to create a instance via function , this function will be called construction function , normally it used to init the params , and the instance will take the construction function own property or method and prototype's property or method from the construction function .
third : the instance's property of "__proto__" is refer to the construction function's prototype object . this is why the instance can use the prototype's property or method from the construction function .
forth : if you create the instance by new , the this will refer to the instance object ! so that instance can use the property and method .
from your code :
var _prototypeProperties = function (child, staticProps, instanceProps) {
if (staticProps){
Object.defineProperties(child, staticProps)
};
// the properties from the own construction function , like this :
// this.element = element;
// this.initialized = false;
if (instanceProps) {
Object.defineProperties(child.prototype, instanceProps);
}
};
// the properties from the construction function's prototype object . like this :
// MyObjectConstructor.prototype.name = 'somebody';
// MyObjectConstructor.prototype.getName = function(){
// return this.name;
// }
In some Javascript code (node.js specifically), I need to call a function with an unknown set of arguments without changing the context. For example:
function fn() {
var args = Array.prototype.slice.call(arguments);
otherFn.apply(this, args);
}
The problem in the above is that when I call apply, I'm change the context by passing this as the first argument. I'd like to pass args to the function being called without changing the context of the function being called. I essentially want to do this:
function fn() {
var args = Array.prototype.slice.call(arguments);
otherFn.apply(<otherFn's original context>, args);
}
Edit: Adding more detail regarding my specific question. I am creating a Client class that contains a socket (socket.io) object among other info pertaining to a connection. I am exposing the socket's event listeners via the client object itself.
class Client
constructor: (socket) ->
#socket = socket
#avatar = socket.handshake.avatar
#listeners = {}
addListener: (name, handler) ->
#listeners[name] ||= {}
#listeners[name][handler.clientListenerId] = wrapper = =>
# append client object as the first argument before passing to handler
args = Array.prototype.slice.call(arguments)
args.unshift(this)
handler.apply(this, args) # <---- HANDLER'S CONTEXT IS CHANGING HERE :(
#socket.addListener(name, wrapper)
removeListener: (name, handler) ->
try
obj = #listeners[name]
#socket.removeListener(obj[handler.clientListenerId])
delete obj[handler.clientListenerId]
Note that clientListenerId is a custom unique identifier property that is essentially the same as the answer found here.
If I understand you correctly:
changes context
| n | y |
accepts array n | func() | func.call() |
of arguments y | ???????? | func.apply() |
PHP has a function for this, call_user_func_array. Unfortunately, JavaScript is lacking in this regard. It looks like you simulate this behavior using eval().
Function.prototype.invoke = function(args) {
var i, code = 'this(';
for (i=0; i<args.length; i++) {
if (i) { code += ',' }
code += 'args[' + i + ']';
}
eval(code + ');');
}
Yes, I know. Nobody likes eval(). It's slow and dangerous. However, in this situation you probably don't have to worry about cross-site scripting, at least, as all variables are contained within the function. Really, it's too bad that JavaScript doesn't have a native function for this, but I suppose that it's for situations like this that we have eval.
Proof that it works:
function showArgs() {
for (x in arguments) {console.log(arguments[x]);}
}
showArgs.invoke(['foo',/bar/g]);
showArgs.invoke([window,[1,2,3]]);
Firefox console output:
--
[12:31:05.778] "foo"
[12:31:05.778] [object RegExp]
[12:31:05.778] [object Window]
[12:31:05.778] [object Array]
Simply put, just assign the this to what you want it to be, which is otherFn:
function fn() {
var args = Array.prototype.slice.call(arguments);
otherFn.apply(otherFn, args);
}
'this' is a reference to your function's context. That's really the point.
If you mean to call it in the context of a different object like this:
otherObj.otherFn(args)
then simply substitute that object in for the context:
otherObj.otherFn.apply(otherObj, args);
That should be it.
If you bind the function to an object and you use everywhere the bound function, you can call apply with null, but still get the correct context
var Person = function(name){
this.name = name;
}
Person.prototype.printName = function(){
console.log("Name: " + this.name);
}
var bob = new Person("Bob");
bob.printName.apply(null); //window.name
bob.printName.bind(bob).apply(null); //"Bob"
One way that you can work around the change of context that can happen in JavaScript when functions are called, is to use methods that are part of the object's constructor if you need them to be able to operate in a context where this is not going to mean the parent object, by effectively creating a local private variable to store the original this identifier.
I concede that - like most discussions of scope in JavaScript - this is not entirely clear, so here is an example of how I have done this:
function CounterType()
{
var counter=1;
var self=this; // 'self' will now be visible to all
var incrementCount = function()
{
// it doesn't matter that 'this' has changed because 'self' now points to CounterType()
self.counter++;
};
}
function SecondaryType()
{
var myCounter = new CounterType();
console.log("First Counter : "+myCounter.counter); // 0
myCounter.incrementCount.apply(this);
console.log("Second Counter: "+myCounter.counter); // 1
}
These days you can use rest parameters:
function fn(...args) {
otherFn(...args);
}
The only downside is, if you want to use some specific params in fn, you have to extract it from args:
function fn(...args) {
let importantParam = args[2]; //third param
// ...
otherFn(...args);
}
Here's an example to try (ES next version to keep it short):
// a one-line "sum any number of arguments" function
const sum = (...args) => args.reduce((sum, value) => sum + value);
// a "proxy" function to test:
var pass = (...args) => sum(...args);
console.log(pass(1, 2, 15));
I'm not going to accept this as an answer, as I'm still hoping for something more suitable. But here's the approach I'm using right now based upon the feedback on this question so far.
For any class that will be calling Client.prototype.addListener or Client.prototype.removeListener, I did added the following code to their constructor:
class ExampleClass
constructor: ->
# ...
for name, fn of this
this[name] = fn.bind(this) if typeof(fn) == 'function'
message: (recipient, body) ->
# ...
broadcast: (body) ->
# ...
In the above example, message and broadcast will always be bound to the new ExampleClass prototype object when it's instantiated, allowing the addListener code in my original question to work.
I'm sure some of you are wondering why I didn't just do something like the following:
example = new ExampleClass
client.addListener('message', example.bind(example))
# ...
client.removeListener('message', example.bind(example))
The problem is that every time .bind( ) is called, it's a new object. So that means that the following is true:
example.bind(example) != example.bind(example)
As such, the removeListener would never work successfully, thus my binding the method once when the object is instantiated.
Since you seem to want to be using the bind function as it is defined in Javascript 1.8.5, and be able to retrieve the original this object you pass the bind function, I recommend redefining the Function.prototype.bind function:
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") {
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function () {},
fBound = function () {
return fToBind.apply(this instanceof fNOP && oThis
? this
: oThis,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
/** here's the additional code **/
fBound.getContext = function() {
return oThis;
};
/**/
return fBound;
};
Now you can retrieve the original context that you called the bind function with:
function A() {
return this.foo+' '+this.bar;
}
var HelloWorld = A.bind({
foo: 'hello',
bar: 'world',
});
HelloWorld(); // returns "hello world";
HelloWorld.getContext(); // returns {foo:"hello", bar:"world"};
I was just reminded of this question after a long time. Looking back now, I think what I was really trying to accomplish here was something similar to how the React library works with its automatic binding.
Essentially, each function is a wrapped bound function being called:
function SomeClass() {
};
SomeClass.prototype.whoami = function () {
return this;
};
SomeClass.createInstance = function () {
var obj = new SomeClass();
for (var fn in obj) {
if (typeof obj[fn] == 'function') {
var original = obj[fn];
obj[fn] = function () {
return original.apply(obj, arguments);
};
}
}
return obj;
};
var instance = SomeClass.createInstance();
instance.whoami() == instance; // true
instance.whoami.apply(null) == instance; // true
Just push properties directly to the function's object and call it with it's own "context".
function otherFn() {
console.log(this.foo+' '+this.bar); // prints: "hello world" when called from rootFn()
}
otherFn.foo = 'hello';
otherFn.bar = 'world';
function rootFn() {
// by the way, unless you are removing or adding elements to 'arguments',
// just pass the arguments object directly instead of casting it to Array
otherFn.apply(otherFn, arguments);
}