sindresorhus / auto-bind Goto Github PK
View Code? Open in Web Editor NEWAutomatically bind methods to their class instance
License: MIT License
Automatically bind methods to their class instance
License: MIT License
Line 38 in 2579065
I'm not using react, but the @types/react
is installed. …(⊙_⊙;)…
Currently this doesn't support getters / setters. Using descriptors would fix this:
const desc = Object.getOwnPropertyDescriptors(self.constructor.prototype);
for (const key of Object.keys(desc)) {
const val = desc[key].get || desc[key].value;
// etc
}
Just a thought.
Edit: Logic would be a bit different. If you find a get
you'd want to look for the appropriate set
as well. You get the idea.
Thanks for creating this project. I see that there has been at least one fork that added React specific filters when choosing which methods to bind. I'd really like to make this a more general purpose mechanism. For example, if you just wanted to bind all methods that started with the word handle
which is the convention that I use for event handler methods in React apps. I propose:
Neither of these additions would affect current users in any way. If I prepared a PR would you be interested in merging it?
The ES2015ify-ing it broke the ability to use it in a web environment that's not Chrome 😢
I saw previous issue about this (#4), however in v1.2.0 React support was added.
Would you consider transpiling the arrow functions now?
From Pierre Arnaud's article, it says
The getter might have a side effect; enumerating the methods of a class instance should not produce side effects.
The getter might be slow.
The getter might return a function; if so, the code would then be mistaken and classify the getter as a method.
The getter might throw an exception.
In the article, it is suggested that the code below resolves the issue.
function getInstanceMethodNames (obj, stop) {
let array = [];
let proto = Object.getPrototypeOf (obj);
while (proto && proto !== stop) {
Object.getOwnPropertyNames (proto)
.forEach (name => {
if (name !== 'constructor') {
if (hasMethod (proto, name)) {
array.push (name);
}
}
});
proto = Object.getPrototypeOf (proto);
}
return array;
}
with
function hasMethod (obj, name) {
const desc = Object.getOwnPropertyDescriptor (obj, name);
return !!desc && typeof desc.value === 'function';
}
Was wondering if I was doing anything weird or odd, as to why auto-bind completely fails on React.
Realised because the this
becomes a ProxyComponent
during HMR.
Similar #5 in that methods become inherited instead.
I ran into a lot of troubles with this when I extended a class (using nodejs v8). Since auto-bind uses 'getOwnPropertyNames' to retrieve the methods of a class, then it will never get the methods of a parent class. Also, if called in a parent class, it rebinds methods. See the following code.
const autoBind = require('auto-bind');
class A {
constructor() {
this.val = 'A';
autoBind(this);
}
method2() { console.log('A.method2 ', this.val); }
}
class B extends A {
constructor() {
super();
this.val = 'B';
autoBind(this);
}
method1() { console.log('B.method1 ', this.val); }
}
let a = new A();
let b = new B();
b.method1(); // B.method 1 B
b.method2(); // A.method2 B
let mb1 = b.method1;
let mb2 = b.method2;
console.log(mb1.name); // bound bound method1
console.log(mb2.name); // method2
mb1(); // B.method1 B
mb2(); // throws error since no 'this' when calling for 'this.val'
The magic of Stackoverflow helped me cobble together an answer using a function that finds all properties of an object by going through the prototype chain. Then we try to bind these with 'self'. Additionally, I put in a check for already bound methods through the startsWith('bound ')
call.
Would love to see comments and feedback.
/**
* A copy of auto-bind for debugging.
* @param {object} self - object to bind its own functions to
* @param {string} _fn - filename
* @return {this}
*/
module.exports = (self, _fn) => {
for (const key of getAllPropertyNames(self)) {
const val = self[key];
if (key !== 'constructor' && typeof val === 'function' &&
(!self[key].name.startsWith('bound ')) ) {
self[key] = val.bind(self);
// console.log(` --- bind '${key}' as '${self[key].name}'`);
}
}
return self;
};
/**
* Get all property names by walking up prototype chain
* @param {*} obj
* @return {array}
*/
function getAllPropertyNames( obj ) {
let props = [];
do {
Object.getOwnPropertyNames( obj )
.forEach(( prop ) => {
if ( props.indexOf( prop ) === -1 ) {props.push( prop );}
});
} while ( obj = Object.getPrototypeOf( obj ) );
return props;
};
Hi, I used this library on react-native
for a long time, and works perfect. But now I'm trying to enable Hermes engine and I having this error.
I think that this happen because Hermes doesn't support Reflect.
The error is originated in this line:
Line 8 in 1f3e975
const {get} = new class MEEEE {get = () => this}
get(); // MEEEE
I can't find exactly which version of Node supports this, but auto-bind
isn't necessary anymore once that's targeted.
hi
Hello, when I used Auto-Bind version 5.0.1 in TypeScript
Error:
Error [ERR_REQUIRE_ESM]: require() of ES Module
How can I fix it?
Uglify doesn't support es6 syntax and we're not supposed to run babel on node_modules
so it returns the following error.
ERROR in bundle.js from UglifyJs
Unexpected token: operator (>) [bundle.js:20620,23]
It took me a while to actually open the bundle file and check the line, for I thought I was doing something wrong. Then I had to figure out which dependency this was from. Ok, this part wasn't so difficult. haha
module.exports = self => {
for (const key of Object.getOwnPropertyNames(self.constructor.prototype)) {
const val = self[key];
if (key !== 'constructor' && typeof val === 'function') {
self[key] = val.bind(self);
}
}
};
I would submit a PR changing the arrow function syntax, but I'm not sure const
should also be changed.
I get the following error when trying to write unit tests using jest in a react typescript project using mobx.
export default function autoBind(self, {include, exclude} = {}) {
^^^^^^
SyntaxError: Unexpected token 'export'
current babel.config.js file:
module.exports = {
presets: [
'@babel/preset-env',
'@babel/preset-react',
'@babel/preset-typescript',
],
plugins: ['@babel/plugin-transform-runtime'],
};
jest.config.ts:
const config: Config = {
preset: 'ts-jest',
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['<rootDir>/setup-jest.ts'],
transformIgnorePatterns: [`<rootDir>/node_modules/(?!auto-bind)`],
};
Any solution for this?
what is this!?
What can I do to solve this problem?
> tsc && node dist
node_modules/auto-bind/index.d.ts:1:24 - error TS2307: Cannot find module 'react'.
1 import * as react from `'react';
Hello,
I'm a first time user of this project. I installed auto-bind, and added it to a single class to try it out. When I tried to compile it, webpack/babel spit out this error message:
ERROR in C:/projects/qbdvision/node_modules/auto-bind/react.js
Module parse failed: Unexpected token (22:39)
You may need an appropriate loader to handle this file type.
| ];
|
| module.exports = (self, {exclude = [], ...options} = {}) => {
| options.exclude = [
| ...exclude,
@ C:/projects/qbdvision/build/main/clientjs/processExplorer/process_explorer_page.jsx 12:37-63
Any ideas for me? I'm actually confused about what you're trying to do. I think the last argument should be {exclude, ...options} = {exclude: []}
, right? Or perhaps this is some new double default syntax that I'm not aware of.
I'm using:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.