Javascript React 中的这三个点有什么作用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31048953/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 06:07:36  来源:igfitidea点击:

What do these three dots in React do?

javascriptreactjs

提问by Thomas Johansen

What does the ...do in this React (using JSX) code and what is it called?

什么是...在这个做反应(使用JSX)代码,什么是它叫什么名字?

<Modal {...this.props} title='Modal heading' animation={false}>

回答by T.J. Crowder

That's property spread notation. It was added in ES2018 (spread for arrays/iterables was earlier, ES2015), but it's been supported in React projects for a long time via transpilation (as "JSX spread attributes" even though you could do it elsewhere, too, not just attributes).

那是财产传播符号。它是在 ES2018 中添加的(用于数组/可迭代对象的传播更早,ES2015),但它在 React 项目中通过转译得到了很长时间的支持(作为“ JSX 传播属性”,即使你也可以在其他地方做到这一点,而不仅仅是属性) )。

{...this.props}spreads outthe "own" enumerable properties in propsas discrete properties on the Modalelement you're creating. For instance, if this.propscontained a: 1and b: 2, then

{...this.props}“自己的”可枚举属性props作为Modal您正在创建的元素的离散属性展开。例如,如果this.props包含a: 1and b: 2,则

<Modal {...this.props} title='Modal heading' animation={false}>

would be the same as

将与

<Modal a={this.props.a} b={this.props.b} title='Modal heading' animation={false}>

But it's dynamic, so whatever "own" properties are in propsare included.

但它是动态的,所以任何“自己的”属性props都包括在内。

Since childrenis an "own" property in props, spread will include it. So if the component where this appears had child elements, they'll be passed on to Modal. Putting child elements between the opening tag and closing tags is just syntactic sugar — the good kind — for putting a childrenproperty in the opening tag. Example:

由于children是 中的“拥有”属性props,因此传播将包括它。因此,如果出现它的组件有子元素,它们将被传递到Modal. 将子元素放在开始标签和结束标签之间只是语法糖 - 很好的一种 - 用于children在开始标签中放置属性。例子:

class Example extends React.Component {
  render() {
    const { className, children } = this.props;
    return (
      <div className={className}>
      {children}
      </div>
    );
  }
}
ReactDOM.render(
  [
    <Example className="first">
      <span>Child in first</span>
    </Example>,
    <Example className="second" children={<span>Child in second</span>} />
  ],
  document.getElementById("root")
);
.first {
  color: green;
}
.second {
  color: blue;
}
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Spread notation is handy not only for that use case, but for creating a new object with most (or all) of the properties of an existing object — which comes up a lot when you're updating state, since you can't modify state directly:

展开表示法不仅适用于该用例,而且适用于创建具有现有对象的大部分(或全部)属性的新对象——当您更新状态时会出现很多情况,因为您无法修改状态直接地:

this.setState(prevState => {
    return {foo: {...prevState.foo, a: "updated"}};
});

That replaces this.state.foowith a new object with all the same properties as fooexcept the aproperty, which becomes "updated":

这将替换this.state.foo为一个新对象,该对象具有foo除该a属性之外的所有相同属性,该对象变为"updated"

const obj = {
  foo: {
    a: 1,
    b: 2,
    c: 3
  }
};
console.log("original", obj.foo);
// Creates a NEW object and assigns it to `obj.foo`
obj.foo = {...obj.foo, a: "updated"};
console.log("updated", obj.foo);
.as-console-wrapper {
  max-height: 100% !important;
}

回答by Mehdi Raash

As you know ...are called Spread Attributeswhich the name represents it allows an expression to be expanded.

如您所知,它 ...被称为扩展属性,它的名称代表它允许扩展表达式。

var parts = ['two', 'three'];
var numbers = ['one', ...parts, 'four', 'five']; // ["one", "two", "three", "four", "five"]

And in this case(I'm gonna simplify it).

在这种情况下(我要简化它)。

//just assume we have an object like this:
var person= {
    name: 'Alex',
    age: 35 
}

This:

这个:

<Modal {...person} title='Modal heading' animation={false} />

is equal to

等于

<Modal name={person.name} age={person.age} title='Modal heading' animation={false} />

So in short, it's a neatshort-cut, we can say.

简而言之,这是一个简洁的捷径,我们可以说

回答by theTypan

The three dots represent the Spread Operatorin ES6. It allows us to do quite a few things in Javascript:

三个点代表ES6 中的扩展运算符。它允许我们在 Javascript 中做很多事情:

  1. Concatenate arrays

    var shooterGames = ['Call of Duty', 'Far Cry', 'Resident Evil'];
    var racingGames = ['Need For Speed', 'Gran Turismo', 'Burnout'];
    var games = [...shooterGames, ...racingGames];
    
    console.log(games)  // ['Call of Duty', 'Far Cry', 'Resident Evil',  'Need For Speed', 'Gran Turismo', 'Burnout']
    
  2. Destructuring an array

      var shooterGames = ['Call of Duty', 'Far Cry', 'Resident Evil'];
      var [first, ...remaining] = shooterGames;
      console.log(first); //Call of Duty
      console.log(remaining); //['Far Cry', 'Resident Evil']
    
  3. Combining two objects

    var myCrush = {
      firstname: 'Selena',
      middlename: 'Marie'
    };
    
    var lastname = 'my last name';
    
    var myWife = {
      ...myCrush,
      lastname
    }
    
    console.log(myWife); // {firstname: 'Selena',
                         //   middlename: 'Marie',
                         //   lastname: 'my last name'}
    
  1. 连接数组

    var shooterGames = ['Call of Duty', 'Far Cry', 'Resident Evil'];
    var racingGames = ['Need For Speed', 'Gran Turismo', 'Burnout'];
    var games = [...shooterGames, ...racingGames];
    
    console.log(games)  // ['Call of Duty', 'Far Cry', 'Resident Evil',  'Need For Speed', 'Gran Turismo', 'Burnout']
    
  2. 解构数组

      var shooterGames = ['Call of Duty', 'Far Cry', 'Resident Evil'];
      var [first, ...remaining] = shooterGames;
      console.log(first); //Call of Duty
      console.log(remaining); //['Far Cry', 'Resident Evil']
    
  3. 组合两个对象

    var myCrush = {
      firstname: 'Selena',
      middlename: 'Marie'
    };
    
    var lastname = 'my last name';
    
    var myWife = {
      ...myCrush,
      lastname
    }
    
    console.log(myWife); // {firstname: 'Selena',
                         //   middlename: 'Marie',
                         //   lastname: 'my last name'}
    

There's another use for the three dots which is known as Rest Parametersand it makes it possible to take all of the arguments to a function in as one array.

这三个点还有另一种用途,称为Rest 参数,它可以将函数的所有参数作为一个数组。

  1. Function arguments as array

     function fun1(...params) { 
    
     }  
    
  1. 函数参数作为数组

     function fun1(...params) { 
    
     }  
    

回答by Tomas Nikodym

The three dots in JavaScript are spread / rest operator.

JavaScript 中的三个点是spread / rest operator

Spread operator

展开运算符

The spread syntaxallows an expression to be expanded in places where multiple arguments are expected.

价差语法允许表达在多个参数预期的地方进行扩展。

myFunction(...iterableObj);

[...iterableObj, 4, 5, 6]

[...Array(10)]

Rest parameters

休息参数

The restparameter syntax is used for functions with variable number of arguments.

其余参数语法用于与可变参数数目的功能。

function(a, b, ...theArgs) {
  // ...
}

The spread / rest operator for arrays was introduced in ES6. There's a State 2 proposalfor object spread / rest properties.

ES6 中引入了数组的扩展/休息运算符。有一个关于对象传播/休息属性的状态 2提案

TypeScript also supports the spread syntax and can transpile that into older versions of ECMAScript with minor issues.

TypeScript 还支持扩展语法,并且可以将其转换为旧版本的 ECMAScript,但存在一些小问题

回答by Negin

This is a feature of ES6, which is used in React as well. Look at the below example:

这是 ES6 的一个特性,它也在 React 中使用。看下面的例子:

function Sum(x,y,z) {
   return x + y + z;
}
console.log(Sum(1,2,3)); //6

This way is fine if we have a maximum of 3 parameters. But, what if we need to add for example 110 parameters. Should we define them all and add them one by one?

如果我们最多有 3 个参数,这种方式就很好。但是,如果我们需要添加例如 110 个参数怎么办。我们是否应该将它们全部定义并一一添加?

Of course there is an easier way to do, which is called SPREAD. Instead of passing all those parameters you write :

当然,还有一种更简单的方法,称为SPREAD。而不是传递所有这些参数你写:

function (...numbers){} 

We have no idea how many parameters we have, but we know there are heaps of those. Based on ES6, we can rewrite the above function as below and use the spread and mapping between them to make it as easy as a piece of cake:

我们不知道我们有多少参数,但我们知道有很多参数。基于 ES6,我们可以将上面的函数重写如下,并利用它们之间的传播和映射,让它变得轻而易举:

let Sum = (...numbers) => {
return numbers.reduce((prev, current) => prev + current );
}
console.log(Sum(1, 2, 3, 4, 5, 6, 7, 8, 9));//45

回答by Alireza

It's just defining propsin a different way in JSXfor you!

它只是在JSX 中为您以不同的方式定义props

It's using ...array and object operator in ES6 (object one not fully supported yet), so basically if you already define your props, you can pass it to your element this way.

...在 ES6 中使用数组和对象运算符(尚未完全支持对象一),所以基本上如果你已经定义了你的道具,你可以通过这种方式将它传递给你的元素。

So in your case, the code should be something like this:

所以在你的情况下,代码应该是这样的:

function yourA() {
  const props = {name='Alireza', age='35'};
  <Modal {...props} title='Modal heading' animation={false} />
}

so the props you defined, now separated and can be reused if necessary.

所以你定义的道具现在分开了,必要时可以重用。

It's equal to:

它等于:

function yourA() {
  <Modal name='Alireza' age='35' title='Modal heading' animation={false} />
}

These are the quotes from React team about spread operator in JSX:

这些是 React 团队关于 JSX 中扩展运算符的引用:

JSX Spread Attributes If you know all the properties that you want to place on a component ahead of time, it is easy to use JSX:

JSX 扩展属性如果您提前知道要放置在组件上的所有属性,那么使用 JSX 很容易:

var component = <Component foo={x} bar={y} />;

Mutating Props is Bad
If you don't know which properties you want to set, you might be tempted to add them onto the object later:

改变道具是不好的
如果你不知道你想设置哪些属性,你可能会想稍后将它们添加到对象中:

var component = <Component />;
component.props.foo = x; // bad
component.props.bar = y; // also bad

This is an anti-pattern because it means that we can't help you check the right propTypes until way later. This means that your propTypes errors end up with a cryptic stack trace.

The props should be considered immutable. Mutating the props object somewhere else could cause unexpected consequences so ideally it would be a frozen object at this point.

Spread Attributes
Now you can use a new feature of JSX called spread attributes:

这是一种反模式,因为这意味着我们无法帮助您检查正确的 propTypes 直到稍后。这意味着您的 propTypes 错误以神秘的堆栈跟踪结束。

props 应该被认为是不可变的。在其他地方改变 props 对象可能会导致意想不到的后果,因此理想情况下,此时它应该是一个冻结的对象。

传播属性
现在您可以使用 JSX 的一项新功能,称为传播属性:

var props = {};
    props.foo = x;
    props.bar = y;
    var component = <Component {...props} />;

The properties of the object that you pass in are copied onto the component's props.

You can use this multiple times or combine it with other attributes. The specification order is important. Later attributes override previous ones.

您传入的对象的属性被复制到组件的道具上。

您可以多次使用它或将其与其他属性结合使用。规范顺序很重要。以后的属性会覆盖以前的属性。

var props = { foo: 'default' };
var component = <Component {...props} foo={'override'} />;
console.log(component.props.foo); // 'override'

What's with the weird ... notation?
The ... operator (or spread operator) is already supported for arrays in ES6. There is also an ECMAScript proposal for Object Rest and Spread Properties. We're taking advantage of these supported and developing standards in order to provide a cleaner syntax in JSX.

奇怪的...符号是怎么回事?
ES6 中的数组已经支持 ... 运算符(或展开运算符)。还有一个针对 Object Rest 和 Spread 属性的 ECMAScript 提案。我们正在利用这些支持和开发的标准,以便在 JSX 中提供更清晰的语法。

回答by Andre Miras

For those who come from the Python world, JSX Spread Attributes are equivalent to Unpacking Argument Lists(the Python **-operator).

对于那些来自 Python 世界的人来说,JSX 扩展属性相当于 解包参数列表(Python **-operator)。

I'm aware this is a JSX question, but working with analogies sometimes helps to get it faster.

我知道这是一个 JSX 问题,但使用类比有时有助于加快速度。

回答by daniel maina

The ...(spread operator) is used in react to:

...(扩展操作符)用于在反应:

provide a neat way to pass props from parent to child components. e.g given these props in a parent component,

提供一种巧妙的方式将 props 从父组件传递到子组件。例如,在父组件中给出这些道具,

this.props = {
  username: "danM",
  email: "[email protected]"
}

they could be passed in the following manner to the child,

它们可以通过以下方式传递给孩子,

<ChildComponent {...this.props} />

which is similar to this

与此类似

<ChildComponent username={this.props.username} email={this.props.email} />

but way cleaner.

但方式更清洁。

回答by Code_Mode

Three dots ...represents Spread Operatorsor Rest Parameters,

三个点...代表扩展运算符休息参数

It allows an array expression or string or anything which can be iteratingto be expanded in places where zero or more arguments for function calls or elements for array are expected.

它允许数组表达式或字符串或任何可以迭代的东西在需要零个或多个函数调用参数或数组元素的地方进行扩展。

  • Merge two arrays
  • 合并两个数组

var arr1 = [1,2,3];
var arr2 = [4,5,6];

arr1 = [...arr1, ...arr2];
console.log(arr1);  //[1, 2, 3, 4, 5, 6]

  • Copying array:
  • 复制数组:

var arr = [1, 2, 3];
var arr2 = [...arr];

console.log(arr); //[1, 2, 3]

Note: Spread syntax effectively goes one level deep while copying an array. Therefore, it may be unsuitable for copying multidimensional arrays as the following example shows (it's the same with Object.assign() and spread syntax).

注意:在复制数组时,Spread 语法有效地深入一层。因此,它可能不适合复制多维数组,如下例所示(与 Object.assign() 和 spread 语法相同)。

  • Add values of one array to other at specific index e.g 3:
  • 在特定索引处将一个数组的值添加到另一个数组,例如 3:

var arr1 = [4,5]
var arr2 = [1,2,3,...arr1,6]
console.log(arr2); // [1, 2, 3, 4, 5, 6]

  • When calling a constructor with new:
  • 使用 new 调用构造函数时:

var dateFields = [1970, 0, 1];  // 1 Jan 1970
var d = new Date(...dateFields);

console.log(d);

  • Spread in object literals:
  • 在对象字面量中传播:

var obj1 = { foo: 'bar', x: 42 };
var obj2 = { foo: 'baz', y: 13 };

var clonedObj = { ...obj1 };
console.log(clonedObj); //{foo: "bar", x: 42}

var mergedObj = { ...obj1, ...obj2 };
console.log(mergedObj); //{foo: "baz", x: 42, y: 13}

Note that fooproperty of obj1 has been overwritten by obj2 fooproperty

请注意,fooobj1 的属性已被 obj2foo属性覆盖

  • As a rest parameter syntax which allows us to represent an indefinite number of arguments as an array:
  • 作为一种剩余参数语法,它允许我们将无限数量的参数表示为一个数组:

function sum(...theArgs) {
  return theArgs.reduce((previous, current) => {
    return previous + current;
  });
}

console.log(sum(1, 2, 3)); //6
console.log(sum(1, 2, 3, 4)); //10

Note:Spread syntax (other than in the case of spread properties) can be applied only to iterable objects:So following will throw error

注意:Spread 语法(除了在 spread 属性的情况下)只能应用于可迭代对象:因此以下将引发错误

var obj = {'key1': 'value1'};
var array = [...obj]; // TypeError: obj is not iterable

Reference1

参考文献1

Reference2

参考文献2

回答by curiousBoy

Kudos to Brandon Morelli.He explained perfectly here, but links may die so I am just pasting the content below:

感谢布兰登·莫雷利。在这里解释得很好,但链接可能会死,所以我只是粘贴下面的内容:

The spread syntax is simply three dots: ...It allows an iterable to expand in places where 0+ arguments are expected. Definitions are tough without context. Let's explore some different use cases to help understand what this means.

展开语法只是三个点:...它允许可迭代对象在需要 0+ 个参数的地方扩展。没有上下文,定义很难。让我们探索一些不同的用例来帮助理解这意味着什么。

Example #1 — Inserting ArraysTake a look at the code below. In this code, we don't use the spread syntax:

Example #1 - 插入数组看看下面的代码。在这段代码中,我们不使用传播语法:

var mid = [3, 4];
var arr = [1, 2, mid, 5, 6];

console.log(arr);

Above, we've created an array named mid. We then create a second array which contains our midarray. Finally, we log out the result. What do you expect arrto print? Click run above to see what happens. Here is the output:

上面,我们创建了一个名为mid. 然后我们创建包含我们的mid数组的第二个数组。最后,我们注销结果。您希望arr打印什么?单击上面的运行以查看会发生什么。这是输出:

[1, 2, [3, 4], 5, 6]

Is that the result you expected? By inserting the midarray into the arrarray, we've ended up with an array within an array. That's fine if that was the goal. But what if you want only a single array with the values of 1 through 6? To accomplish this, we can use the spread syntax! Remember, the spread syntax allows the elements of our array to expand. Lets look at the code below. Everything is the same — except we're now using the spread syntax to insert the midarray into the arrarray:

这是你期望的结果吗?通过将mid数组插入arr数组,我们最终得到了数组中的数组。如果这是目标就好了。但是如果您只想要一个值为 1 到 6 的数组呢?为此,我们可以使用传播语法!请记住,展开语法允许扩展数组的元素。让我们看看下面的代码。一切都一样——除了我们现在使用扩展语法将mid数组插入到arr数组中:

var mid = [3, 4];
var arr = [1, 2, ...mid, 5, 6];

console.log(arr);

And when you hit the run button, here's the result:

当您点击运行按钮时,结果如下:

[1, 2, 3, 4, 5, 6]

Awesome! Remember the spread syntax definition you just read above? Here's where it comes into play. As you can see, when we create the arrarray and use the spread operator on the midarray, instead of just being inserted, the midarray expands. This expansion means that each and every element in the midarray is inserted into the arrarray. Instead of nested arrays, the result is a single array of numbers ranging from 1 to 6.

惊人的!还记得你刚刚在上面读到的传播语法定义吗?这就是它发挥作用的地方。如您所见,当我们创建arr数组并在数组上使用扩展运算符时,mid数组不仅被插入,而且mid会扩展。这种扩展意味着mid数组中的每个元素都被插入到arr数组中。结果不是嵌套数组,而是一个范围从 1 到 6 的数字数组。

Example #2 — MathJavaScript has a built in math object that allows us to do some fun math calculations. In this example we'll be looking at Math.max(). If you're unfamiliar, Math.max()returns the largest of zero or more numbers. Here are a few examples:

Example #2 — MathJavaScript 有一个内置的 math 对象,它允许我们进行一些有趣的数学计算。在此示例中,我们将查看Math.max(). 如果您不熟悉,则Math.max()返回零个或多个数字中最大的一个。这里有一些例子:

Math.max();
// -Infinity
Math.max(1, 2, 3);
// 3
Math.max(100, 3, 4);
// 100

As you can see, if you want to find the maximum value of multiple numbers, Math.max()requires multiple parameters. You unfortunately can't simply use a single array as input. Before the spread syntax, the easiest way to use Math.max()on an array is to use .apply()

可以看到,如果Math.max()要求多个数的最大值,需要多个参数。不幸的是,您不能简单地使用单个数组作为输入。在展开语法之前,在Math.max()数组上使用的最简单方法是使用.apply()

var arr = [2, 4, 8, 6, 0];

function max(arr) {
  return Math.max.apply(null, arr);
}

console.log(max(arr));

It works, it's just really annoying. Now take a look at how we do the same exact thing with the spread syntax:

它有效,只是真的很烦人。现在看看我们如何使用传播语法做同样的事情:

var arr = [2, 4, 8, 6, 0];
var max = Math.max(...arr);

console.log(max);

Instead of having to create a function and utilize the apply method to return the result of Math.max(), we only need two lines of code! The spread syntax expands our array elements and inputs each element in our array individually into the Math.max()method!

Math.max()我们只需要两行代码,而不必创建一个函数并使用 apply 方法来返回 的结果!spread 语法扩展了我们的数组元素并将数组中的每个元素单独输入到Math.max()方法中!

Example #3 — Copy an ArrayIn JavaScript, you can't just copy an array by setting a new variable equal to already existing array. Consider the following code example:

示例 #3 — 复制数组在 JavaScript 中,您不能仅通过将新变量设置为等于现有数组来复制数组。考虑以下代码示例:

var arr = ['a', 'b', 'c'];
var arr2 = arr;

console.log(arr2);

When you press run, you'll get the following output:

当您按运行时,您将获得以下输出:

['a', 'b', 'c']

Now, at first glance, it looks like it worked — it looks like we've copied the values of arr into arr2. But that's not what has happened. You see, when working with objects in javascript (arrays are a type of object) we assign by reference, not by value. This means that arr2 has been assigned to the same reference as arr. In other words, anything we do to arr2 will also affect the original arr array (and vice versa). Take a look below:

现在,乍一看,它看起来有效——看起来我们已经将 arr 的值复制到了 arr2 中。但事实并非如此。你看,当在 javascript 中处理对象(数组是一种对象)时,我们是通过引用而不是值来分配的。这意味着 arr2 已分配给与 arr 相同的引用。换句话说,我们对 arr2 所做的任何事情也会影响原始的 arr 数组(反之亦然)。看看下面:

var arr = ['a', 'b', 'c'];
var arr2 = arr;

arr2.push('d');

console.log(arr);

Above, we've pushed a new element d into arr2. Yet, when we log out the value of arr, you'll see that the d value was also added to that array:

上面,我们已经将一个新元素 d 推入了 arr2。然而,当我们注销 arr 的值时,您会看到 d 值也被添加到该数组中:

['a', 'b', 'c', 'd']

No need to fear though! We can use the spread operator! Consider the code below. It's almost the same as above. Instead though, we've used the spread operator within a pair of square brackets:

不过没必要害怕!我们可以使用扩展运算符!考虑下面的代码。这几乎和上面一样。相反,我们在一对方括号中使用了扩展运算符:

var arr = ['a', 'b', 'c'];
var arr2 = [...arr];

console.log(arr2);

Hit run, and you'll see the expected output:

点击运行,你会看到预期的输出:

['a', 'b', 'c']

Above, the array values in arr expanded to become individual elements which were then assigned to arr2. We can now change the arr2 array as much as we'd like with no consequences on the original arr array:

上面,arr 中的数组值扩展为单个元素,然后分配给 arr2。我们现在可以随意更改 arr2 数组,而不会对原始 arr 数组产生任何影响:

var arr = ['a', 'b', 'c'];
var arr2 = [...arr];

arr2.push('d');

console.log(arr);

Again, the reason this works is because the value of arr is expanded to fill the brackets of our arr2 array definition. Thus, we are setting arr2 to equal the individual values of arr instead of the reference to arr like we did in the first example.

同样,这是因为 arr 的值被扩展以填充我们的 arr2 数组定义的括号。因此,我们将 arr2 设置为等于 arr 的各个值,而不是像我们在第一个示例中所做的那样引用 arr。

Bonus Example — String to ArrayAs a fun final example, you can use the spread syntax to convert a string into an array. Simply use the spread syntax within a pair of square brackets:

额外示例 — 字符串到数组作为最后一个有趣的示例,您可以使用展开语法将字符串转换为数组。只需在一对方括号内使用扩展语法:

var str = "hello";
var chars = [...str];

console.log(chars);