Как мне разобрать строку в число при деструктурировании? - PullRequest
17 голосов
/ 16 марта 2019

Я пытаюсь поэкспериментировать с деструктурирующим заданием. Теперь у меня есть дело, которое я пытаюсь справиться с самоуничтожением.

Например, у меня есть такой ввод:

let input = {latitude: "17.0009", longitude: "82.2108"}

Где значения ключей latitude и longitude являются строками, но я хочу разобрать их в число при деструктурировании.

let input = {latitude: "17.0009", longitude: "82.2108"}
let {latitude,longitude} = input

console.log(typeof latitude,typeof longitude)

Я вижу в babel repl , что для этого требуется ссылка на объект, а затем доступ к каждому ключу. Таким образом, приведенный выше код такой же, как:

"use strict";

 var arr = {
   latitude: "17.0009",
   longitude: "82.2108"
  };
 var latitude = arr.latitude,
     longitude = arr.longitude;

Я хочу сделать что-то вроде использования самого синтаксиса деструктуризации.

"use strict";

var arr = {
  latitude: "17.0009",
  longitude: "82.2108"
};
var latitude = Number(arr.latitude),
    longitude = Number(arr.longitude);

Я тоже открыт, чтобы увидеть некоторые хаки.

Обновление

Я могу прийти с одним взломом с оператором ,:

let arr = {latitude: "17.0009", longitude: "82.2108"}

let {lat,lng} = ({latitude,longitude} = arr, ({lat:+latitude,lng:+longitude}))

console.log(typeof lat, typeof lng)

На заметке: - вы должны прочитать Ответ Морица Росслера это глупо, но содержит хорошие знания и информацию

Ответы [ 7 ]

14 голосов
/ 16 марта 2019

Разрушение - это просто хороший способ распаковать свойства из объектов и массивов и назначить их переменным.Как показывает код в вопросе, который может быть использован, любой вид операции невозможен.

Один хак будет означать создание еще 2 переменных (которых нет в input) иустановите значение по умолчанию равным числу, эквивалентному ранее уничтоженным свойствам:

let input = { latitude: "17.0009", longitude: "82.2108" }
let { latitude, longitude, lat = +latitude, long = +longitude } = input

console.log(typeof latitude, typeof longitude, typeof lat, typeof long)

Код приблизительно Передается к этому ( Babel ):

var latitude = input.latitude,
    longitude = input.longitude,
    lat = input.lat === undefined ? +latitude : input.lat,
    long = input.long === undefined ? +longitude : input.long;

Это просто использованиепорядок, в котором создаются переменные и присваиваются значения свойств.Опять же, это работает, только если в input нет свойств lat или long.В противном случае произойдет сбой троичного условия, и для lat будет установлено значение input.lat.


Примерно так будет легче читать:

let { latitude, longitude } = input;
let lat = +latitude, 
    long = +longitude;

ИЛИ

let [ lat, long ] = [ +latitude, +longitude ]
7 голосов
/ 16 марта 2019

Вы можете деструктурировать значения, взять массив значений и отобразить новый тип данных значения и присвоить эти значения переменным.

let input = { latitude: "17.0009", longitude: "82.2108" },
    { latitude, longitude} = input;

[latitude, longitude] = [latitude, longitude].map(Number);

console.log(typeof latitude, latitude);
console.log(typeof longitude, longitude);
5 голосов
/ 16 марта 2019

У вас может быть функция многократного использования , как показано ниже:

const numberInputs = input =>
    Object.keys(input).reduce((acc, val) => {
        acc[val] = +input[val];
        return acc;
    }, {});

, а затем повторно использовать ее через ...

Затем выполните:

let {latitude,longitude} = numberInputs(input);

console.log(typeof latitude,typeof longitude) //number //number

и получите 17.0009 и 82.2108 в виде чисел ...

Таким образом вы также сохраните свой исходный объект и сделаете копию ... так что у вас есть обаоригинал и копия объекта с номерами в качестве значений ...

4 голосов
/ 16 марта 2019

Хотя вы не можете выполнять преобразование типов в самом выражении деструктурирования, возможной альтернативой / обходным решением может быть деструктурирование свойств в аргументах функции, а затем возврат массива с новыми типами внутри него.

Например, что-то вроде следующего:

const input = {latitude: "17.0009", longitude: "82.2108"}
const [lat, lng] = (({latitude:a, longitude:b}) => [+a, +b])(input);

console.log(typeof lat, typeof lng); // number number

Однако для чего-то подобного я бы не использовал деструктуризацию и, вероятно, прибегнул бы к обычным точечным обозначениям:

const input = {latitude: "17.0009", longitude: "82.2108"}
const lat = +input.latitude;
const lng = +input.longitude;

console.log(typeof lat, typeof lng); // number number
2 голосов
/ 16 марта 2019

Существует супер хакерский способ сделать это, используя геттер, определенный в String.prototype как вспомогательную функцию.

(вы, вероятно, не хотите этого делать)

Object.defineProperty (String.prototype, "asNumber",{
   get: function () { return +this}
});
let input = {latitude: "17.0009", longitude: "82.2108"}
let {latitude:{asNumber:latitude},
     longitude: {asNumber:longitude}} = input

console.log (latitude, longitude)

Давайте разберем это на более простые шаги.

//Extending the `String` prototype means every string 
//will have access to the defined property  via 
//its prototype, so
String.prototype.foo = function () {return `${this}.foo\`} 
//means you can now call foo() like any other string method
"bar".foo() //"bar.foo"`

//A getter allows you to define a function that acts 
//as a property which will be executed upon access. 
let obj = {get getter () {console.log ('Hi');}}
obj.getter // Hi

//Combine those two and you can call functions by 
//accessing properties of strings. 
Object.defineProperty (String.prototype, "asNumber",{
   get: function () { return +this}
});

//Now that you have a property that is available at 
//every string - and make it execute a function; you 
//can convert a string to a number, simply by
//accessing a property
"42".asNumber //42

//To make that work with destructuring assignment, 
//you need to know about another handy feature. You 
//can assign destructured properties to a new 
//variable name.
let {a:b, b:a} = {a:'a', b:'b'};
a; //'b'
b; //'a'

//Since you can nest destructuring assignments, and 
//every string implicitly has a 'asNumber' property, 
//you can destructure that property as well. 

let {lat: {asNumber}} = {lat: "42"};
asNumber //42

//The last thing to know is, there's apparently 
//nothing wrong with using an existing variable as 
//new name for a destructured property. So you can 
//just use the `asNumber` property from the 
//prototype and assign it to the same variable  
//you destructured from the object.
let {lat: {asNumber: lat}} = {lat: "42"};
lat; //42

Нет ничего плохого в использовании того же имени, потому что толькоимя последней переменной будет введено в область действия блока let

2 голосов
/ 16 марта 2019

Это невозможно - никакие операции не могут быть выполнены на объекте во время деструктуры.Если вы используете деструктуризацию для извлечения свойства из переменной, эта переменная будет === к исходному значению свойства.

(конечно, вы могли бы преобразовать значения исходного объекта в Number до деструктуризации, но этоне одно и то же)

0 голосов
/ 16 марта 2019

Я бы, вероятно, настроил все так, чтобы каждый «тип объекта», о котором я заботился, имел соответствующий «тип синтаксического анализатора»: объект с такими же ключами, но значения которого являются соответствующими функциями синтаксического анализа для каждого члена.

Вроде так:

"use strict";

var arr = {
    latitude: "17.0009",
    longitude: "82.2108"
};

function Parser(propParsers)
{
    this.propParsers = propParsers;
    this.parse = function (obj) {
        var result = {};
        var propParsers = this.propParsers;
        Object.keys(obj).forEach(function (k) {
            result[k] = propParsers[k](obj[k]);
        });
        return result;
    };
}

var parser = new Parser({
    latitude: Number,
    longitude: Number
});

let {latitude,longitude} = parser.parse(arr);
console.log(latitude);
console.log(longitude);
...