关于javascript:React中的这三个点有什么作用?

What do these three dots in React do?

...在这个React(使用JSX)代码中做了什么以及它叫什么?

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


这是财产传播符号。它是在ES2018中添加的,但是通过转换在React项目中得到了长期支持(即使你可以在其他地方使用"JSX传播属性",而不仅仅是属性)。

{...this.props}props中的"自己"属性展开为您正在创建的Modal元素的离散属性。例如,如果this.props包含a: 1b: 2,那么

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

会是一样的

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

但它是动态的,因此包括props中的"自有"属性。

由于childrenprops中的"自有"属性,因此spread将包含它。因此,如果出现的组件具有子元素,则它们将被传递给Modal。将子元素放在开始标记和结束标记之间只是语法糖&nbsp;&mdash;善良的&nbsp;&mdash;用于在开始标记中放置children属性。例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Example extends React.Component {
  render() {
    const { className, children } = this.props;
    return (
     
      {children}
     
    );
  }
}
ReactDOM.render(
  [
    <Example className="first">
      <span>Child in first</span>
    </Example>,
    <Example className="second" children={<span>Child in second</span>} />
  ],
  document.getElementById("root")
);
1
2
3
4
5
6
.first {
  color: green;
}
.second {
  color: blue;
}
1
2
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js">
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js">

扩展符号不仅适用于该用例,还适用于创建具有现有对象的大部分(或全部)属性的新对象&nbsp;&mdash;当你更新状态时会出现很多,因为你无法直接修改状态:

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

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

1
2
3
4
5
6
7
8
9
10
11
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);
1
2
3
.as-console-wrapper {
  max-height: 100% !important;
}


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

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

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

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

这个:

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

等于

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

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


这三个点代表ES6中的Spread Operator。它允许我们在Javascript中做很多事情:

  • 复制数组

    1
    2
    3
    4
    5
    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']
  • 解构数组

    1
    2
    3
    4
      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']
  • 函数参数为数组

    1
    2
    3
     function fun1(...params) {

     }
  • 以上称为rest参数,不限制传递给函数的值的数量。但是,参数必须是相同的类型。

  • 梳理两个物体

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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'}

  • JavaScript中的三个点是spread / rest运算符。

    传播运营商

    扩展语法允许在需要多个参数的位置扩展表达式。

    1
    2
    3
    4
    5
    myFunction(...iterableObj);

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

    [...Array(10)]

    休息参数

    rest参数语法用于具有可变数量参数的函数。

    1
    2
    3
    function(a, b, ...theArgs) {
      // ...
    }

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

    TypeScript还支持传播语法,并且可以将其转换为较旧版本的ECMAScript,但存在小问题。


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

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

    如果我们有最多3个参数,这种方式很好,但如果我们需要添加110个参数,那该怎么办呢。我们应该将它们全部定义并逐个添加吗?!
    当然,有一种更简单的方法,称为SPREAD。
    而不是传递你写的所有这些参数:

    1
    function (...numbers){}

    我们不知道我们有多少参数,但我们知道有很多参数。
    基于es6,我们可以重写上面的函数,并使用它们之间的扩展和映射,使它像一块蛋糕一样简单:

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

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

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

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

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

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

    它等于:

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

    以下是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:

    1
    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:

    1
    2
    3
    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:

    1
    2
    3
    4
    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.

    1
    2
    3
    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.


    对于那些来自Python世界的人来说,JSX Spread Attributes相当于
    解压缩参数列表(Python ** -operator)。

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


    ...(扩展运算符)用于对:

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

    1
    2
    3
    4
    this.props = {
      username:"danM",
      email:"[email protected]"
    }

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

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

    这与此类似

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

    但方式更清洁。


    三个点...表示Spread Operators或Rest Parameters,

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

    • 合并两个数组

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

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

    • 复制数组:

    1
    2
    3
    4
    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).

    • 在特定索引处将一个数组的值添加到其他数组,例如3:

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

    • 使用new调用构造函数时:

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

    console.log(d);

    • 传播对象文字:

    1
    2
    3
    4
    5
    6
    7
    8
    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}

    请注意,obj1的foo属性已被obj2 foo属性覆盖

    • 作为rest参数语法,它允许我们将无限数量的参数表示为数组:

    1
    2
    3
    4
    5
    6
    7
    8
    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

    注意:Spread语法(扩展属性除外)只能应用于可迭代对象:
    所以下面会抛出错误

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

    定1

    定2


    三个点(...)称为扩展运算符,这在概念上类似于ES6阵列扩展运算符JSX
    利用这些支持和开发的标准,以便在JSX中提供更清晰的语法

    Spread properties in object initializers copies own enumerable
    properties from a provided object onto the newly created object.

    1
    2
    let n = { x, y, ...z };
    n; // { x: 1, y: 2, a: 3, b: 4 }

    参考:

    1)https://github.com/sebmarkbage/ecmascript-rest-spread#spread-properties

    2)https://facebook.github.io/react/docs/jsx-spread.html


    简而言之,三个点......是ES6中的扩展运算符(ES2015)。 spread运算符将获取所有数据。

    1
    2
    3
    let a = [1, 2, 3, 4];
    let b = [...a, 4, 5, 6];
    let c = [7,8,...a];

    的console.log(b)中;
    给出结果[1,2,3,4,5,6]

    的console.log(C);
    给出结果[7,8,1,2,3,4]


    Spread Attributes used to Pass the the multiple Properties in a Simple Way

    { ... this.props } is Holding the property of this.props

    使用{...} Spread运算符和下面的道具

    1
    2
    3
    4
    5
    6
    7
    this.props =
     {
        firstName: 'Dan',
        lastName: 'Abramov',
        city: 'New York',
        country: 'USA'
    }

    Without { ... } Spread

    1
    2
    3
    4
    5
    6
    7
    <Child
      firstName={this.props.firstName}
      lastName={this.props.lastName}
      city={this.props.city}
      country={this.props.country}

    >

    With { ... } Spread

    1
    <Child { ...this.props } />

    Dan Abramov关于Spread运营商的推文(Redux的创建者)https://twitter.com/dan_abramov/status/694519379191545856?lang=en


    通常称为扩展运算符,它用于扩展所需的任何地方

    1
    2
    3
    4
    const SomeStyle = {
       margin:10,
       background:#somehexa
    }

    你可以在任何需要的地方使用它
    更多关于传播运营商的信息https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax


    ......的含义取决于你在代码中使用它的位置,

  • 用于传播/复制数组/对象 - 它有助于复制数组/对象,还可以添加新数组值/向对象添加新属性,这是可选的。
  • 1
    2
    3
    const numbers = [1,2,3];
    const newNumbers = [...numbers, 4];
    console.log(newNumbers) //prints [1,2,3,4]

    1
    2
    3
    4
    5
    6
    const person = {
     name: 'Max'
    };

    const newPerson = {...person, age:28};
    console.log(newPerson); //prints {name:'Max', age:28}

  • 用于将函数参数合并到单个数组中 - 然后可以在其上使用数组函数。
  • 1
    2
    3
    4
    5
    const filter = (...args) => {
       return args.filter(el => el ===1);
    }

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


    通常的做法是在React应用程序中传递props。在这样做时,我们能够将状态更改应用于子组件,无论它是Pure还是Impure(无状态或有状态)。有时,传递道具时最好的方法是传递单一属性或整个属性对象。由于ES6中对数组的支持,我们得到了"......"符号,现在我们可以实现将整个对象传递给孩子。

    使用以下语法记录了将props传递给子节点的典型过程:

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

    当道具数量最少但在道具数量过高时变得无法管理时,可以使用此功能。当您不知道子组件中所需的属性时,会出现此方法的问题,而典型的JavaScript方法是稍后设置这些属性并稍后绑定到该对象。这会导致propType检查和隐藏堆栈跟踪错误的问题,这些错误无效并导致调试延迟。以下是这种做法的一个例子,以及不该做的事情:

    1
    2
    3
    var component = <Component />;
    component.props.foo = x; // bad
    component.props.bar = y;

    通过这样做可以实现相同的结果,但取得了更为适当的成功:

    1
    2
    3
    4
    var props = {};
    props.foo = x;
    props.bar = y;
    var component = Component(props); // Where did my JSX go?

    但是不使用JSX spread或JSX这样就把它循环回到我们现在可以这样做的等式中:

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

    "...... props"中包含的属性是foo:x,bar:y。这可以与其他属性结合使用以下语法覆盖"... props"的属性:

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

    此外,我们可以将其他属性对象相互复制或以这种方式组合它们:

    1
    2
    3
    4
    var oldObj = { foo: 'hello', bar: 'world' };
    var newObj = { ...oldObj, foo: 'hi' };
    console.log(newObj.foo); // 'hi';
    console.log(newObj.bar); // 'world';

    或者像这样合并两个不同的对象(这在所有反应版本中都不可用):

    1
    var ab = { ...a, ...b }; // merge(a, b)

    根据Facebook的react / docs网站的另一种解释方式是:

    如果您已经将"props"作为对象,并且想要在JSX中传递它,则可以使用"..."作为SPREAD运算符来传递整个props对象。以下两个示例是等效的:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function App1() {
      return <Greeting firstName="Ben" lastName="Hector" />;
    }



    function App2() {
      const props = {firstName: 'Ben', lastName: 'Hector'};
      return <Greeting {...props} />;
    }

    在构建通用容器时,Spread属性非常有用。但是,它们也可以通过简单地将大量不相关的道具传递给不关心它们的组件来使代码变得混乱。应谨慎使用此语法。


    它叫做传播运营商。
    例如
    let hello = {name:'',msg:''}
    让hello1 = {...你好}
    现在将hello对象属性复制到hello1。


    这是ES6 / Harmony的新功能。它被称为传播运营商。
    它允许您分离数组/对象的组成部分,或者将多个项目/参数粘合在一起。
    这是一个例子:

    1
    2
    3
    let array = [1,2,3]
    let array2 = [...array]
    // array2 is now filled with the items from array

    并使用对象/键:

    1
    2
    3
    4
    // lets pass an object as props to a react component
    let myParameters = {myKey: 5, myOtherKey: 7}
    let component = <MyComponent {...myParameters}/>
    // this is equal to <MyComponent myKey=5 myOtherKey=7 />

    真正酷的是你可以用它来表示"其余的价值观"。

    1
    2
    3
    4
    5
    6
    const myFunc = (value1, value2, ...values) {
        // Some code
    }

    myFunc(1, 2, 3, 4, 5)
    // when myFunc is called, the rest of the variables are placed into the"values" array

    它在javascript中称为传播语法。

    它用于在javascript中对数组或对象进行解构。

    例:

    1
    2
    3
    4
    5
    6
    7
    8
    const objA = { a: 1, b: 2, c: 3 }
    const objB = { ...objA, d: 1 }
    /* result of objB will be { a: 1, b: 2, c: 3, d: 1 } */
    console.log(objB)

    const objC = { ....objA, a: 3 }
    /* result of objC will be { a: 3, b: 2, c: 3, d: 1 } */
    console.log(objC)

    您可以在javascript中使用Object.assign()函数执行相同的结果。

    参考:

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax


    那些被称为差价。顾名思义。这意味着它在这些数组或对象中放置它的任何值。

    如 :

    1
    2
    3
    4
    let a = [1, 2, 3];
    let b = [...a, 4, 5, 6];
    console.log(b);
    > [1, 2, 3, 4, 5, 6]