Как работает метод создания копии функции в JavaScript (пример сборника рассказов)

#javascript #ecmascript-6 #storybook

#javascript #ecmascript-6 #сборник рассказов

Вопрос:

Сборник рассказов рекомендует технику создания копии функции:

 const Template = args => <Task {...args} />;
export const Default = Template.bind({});
 

Это позволяет каждой экспортируемой истории устанавливать свои собственные свойства, но использовать ту же реализацию.
Я понимаю результат, но не понимаю, почему он должен привязывать функцию к пустому объекту {}

Ответ №1:

Полный соответствующий код из предоставленной вами ссылки:

 import React from 'react';

import Task from './Task';

export default {
  component: Task,
  title: 'Task',
};

const Template = args => <Task {...args} />;

export const Default = Template.bind({});
Default.args = {
  task: {
    id: '1',
    title: 'Test Task',
    state: 'TASK_INBOX',
    updatedAt: new Date(2018, 0, 1, 9, 0),
  },
};

export const Pinned = Template.bind({});
Pinned.args = {
  task: {
    ...Default.args.task,
    state: 'TASK_PINNED',
  },
};
 

Использование Template.bind({}) позволяет определять дополнительные элементы, такие как Default.args = {...} , по-разному в каждой копии и в оригинале (здесь не используется).

Редактировать

Как уже было сказано в документах по ссылке:

Template.bind({}) это стандартная техника JavaScript для создания копии функции. Мы используем эту технику, чтобы позволить каждой экспортируемой истории устанавливать свои собственные свойства, но использовать ту же реализацию.

Комментарии:

1. Это: Template.bind({}) is a standard JavaScript technique for making a copy of a function. неверно. bind не копирует функцию. Он создает функцию, которая оборачивает исходную функцию.

Ответ №2:

Приведенный выше фрагмент кода используется bind() для функции со стрелкой:

 const Template = args => <Task {...args} />;
export const Default = Template.bind({});
 

Использование bind функции со стрелкой вообще не изменяет поведение функции со стрелкой, поскольку this функция со стрелкой всегда будет областью, в которой была определена функция со стрелкой.

MDN рекомендует не использовать bind в функциях со стрелками выражения функций MDN — Arrow: call, apply и bind

Методы call, apply и bind НЕ подходят для функций со стрелками — поскольку они были разработаны, чтобы позволить методам выполняться в разных областях — потому что функции со стрелками устанавливают «это» на основе области, в которой определена функция со стрелками.

 const arrowFn = () => {
  console.log('this.foo:', this.foo);
};

window.foo = 'window.foo';
const myObj = {
  foo: 'myObj.foo'
};

const boundFn = arrowFn.bind(myObj);

arrowFn();  // 'window.foo'
boundFn();  // 'window.foo' 

Поскольку bind невозможно изменить функцию со стрелкой, единственная полезная вещь bind , которую мы делаем в этом примере выше, — это создание новой функции-оболочки, которая может иметь свои собственные уникальные свойства.

Поэтому код из предоставленного примера:

 const Template = (...args) => {};
const Default = Template.bind({});
Default.args = {...};
 

может быть заменен на:

 const Template = (...args) => {};
Default = function () { Template(...arguments); }
Default.args = {...};
 

Преимущество этого второго шаблона в том, что он не используется bind нестандартным способом.

Комментарии:

1. Это неверно ни в одном из утверждений: bind не переносится в традиционную функцию, выполненное сравнение неверно, второй шаблон не лучше: на самом деле это другое решение (немного менее оптимизированное) и может работать не так, как ожидалось, во всех ситуациях.

2. @emi — Спасибо за комментарии. Я отредактировал ответ. Несмотря на то, что исходный пример «работает», я все же утверждаю, что bind следует избегать использования функции со стрелкой (как указано в MDN).

3. I still submit that using bind on an arrow function should be avoided (as stated in MDN) Это применимо только тогда, когда функция использует this , что не так.

4. Примечание: вопрос специфичен для сборника рассказов, который this не является частью спецификаций и bind используется хорошо документированным способом.

5. @emi — С практической точки зрения документирование нестандартного шаблона менее предпочтительно, чем использование другого шаблона стандартным способом.