Coder Social home page Coder Social logo

auto-bind's Introduction

auto-bind

Automatically bind methods to their class instance

It also correctly binds inherited properties.

If you're targeting Node.js 12 and later or the browser, you should consider using class fields instead.

Install

npm install auto-bind

Usage

import autoBind from 'auto-bind';

class Unicorn {
	constructor(name) {
		this.name = name;
		autoBind(this);
	}

	message() {
		return `${this.name} is awesome!`;
	}
}

const unicorn = new Unicorn('Rainbow');

// Grab the method off the class instance
const message = unicorn.message;

// Still bound to the class instance
message();
//=> 'Rainbow is awesome!'

// Without `autoBind(this)`, the above would have resulted in
message();
//=> Error: Cannot read property 'name' of undefined

API

autoBind(self, options?)

Bind methods in self to their class instance.

Returns the self object.

self

Type: object

An object with methods to bind.

options

Type: object

include

Type: Array<string | RegExp>

Bind only the given methods.

exclude

Type: Array<string | RegExp>

Bind methods except for the given methods.

React

Same as autoBind but excludes the default React component methods.

import autoBindReact from 'auto-bind/react';

class Foo extends React.Component {
	constructor(props) {
		super(props);
		autoBindReact(this);
	}

	// …
}

Related

  • bind-methods - Bind all methods in an object to itself or a specified context

auto-bind's People

Contributors

bendingbender avatar dfoverdx avatar kevinrambaud avatar leehankyeol avatar richienb avatar schnittstabil avatar sindresorhus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

auto-bind's Issues

Babel can't transpile because "Module parse failed: Unexpected token (22:39)"

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:

  • Webpack: 4.8.3
  • @babel/core: 7.11.6
  • @babel/preset-env: 7.11.5
  • @babel/preset-react: 7.10.4

Mention public class fields in readme

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.

Potentially erroneous behavior with `get`, a class getter.

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';
}

Consider supporting getters

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.

Webpack production bundling error

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.

autoBind function needs a filter method

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:

  1. Adding an optional filter method parameter that allows custom filtering of the bind
  2. Adding a predefined filter function to exclude standard React methods.

Neither of these additions would affect current users in any way. If I prepared a PR would you be interested in merging it?

ReferenceError: Property 'Reflect' doesn't exist

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:

for (const key of Reflect.ownKeys(object)) {

Screenshot_20201102-100732

ES2015 arrow function not transpiled

I don't know if this is a babel issue or you should use functions instead of arrow functions because I get an error on old browsers that don't support the new syntax: SyntaxError: Unexpected token '>'

preview

as well const declarations

Does not work with inherited methods of an extended class

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;
};

Doesn't work with Node.js 14 classes

Doesn't work with node.js 14 classes
image

Removing "extends" from .d.ts file fixed this problem
image

Also, seems that Sublime Text can't find module and show error, but all builds well even with error

error [ERR_REQUIRE_ESM]

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?

Jest unit tests failing because of auto-bind

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?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.