Одна разница между реализацией Runnable и продолжением Thread заключается в том, что путем расширения Thread каждый из ваших потоков имеет уникальный объект, связанный с ним, тогда как при реализации Runnable многие потоки могут совместно использовать один и тот же экземпляр объекта.
A класс, который реализует Runnable, не является потоком и просто классом. Чтобы Runnable выполнялся потоком, вам нужно создать экземпляр Thread и передать экземпляр Runnable в качестве цели.
В большинстве случаев интерфейс Runnable должен использоваться, если вы планируете только планировать для переопределения метода run () и других методов Thread. Это важно, потому что классы не должны подклассифицироваться, если программист не намерен модифицировать или улучшать фундаментальное поведение класса.
Когда необходимо расширить суперкласс, реализация интерфейса Runnable более подходит, чем использование класс Thread. Потому что мы можем расширить другой класс, внедряя интерфейс Runnable для создания потока. Но если мы просто расширим класс Thread, мы не сможем наследовать ни от какого другого класса.
Вот что-то более тонкое, хотя оно не позволяет повторить список полей. Он использует «деструктурирование параметров», чтобы избежать необходимости в параметре v
.
({id, title}) => ({id, title})
@ Решение EthanBrown является более общим. Вот более идиоматическая версия, которая использует Object.assign
и вычисленные свойства (часть [p]
):
function pick(o, ...props) {
return Object.assign({}, ...props.map(prop => ({[prop]: o[prop]})));
}
Если мы хотим сохранить атрибуты свойств, такие как configurable
и геттеры и сеттеры, а также опуская неперечислимые свойства, тогда:
function pick(o, ...props) {
var has = p => o.propertyIsEnumerable(p),
get = p => Object.getOwnPropertyDescriptor(o, p);
return Object.defineProperties({},
Object.assign({}, ...props
.filter(prop => has(prop))
.map(prop => ({prop: get(props)})))
);
}
Я имею сходство с решением Итана Брауна, но еще короче - pick
. Другая функция pick2
немного длиннее (и медленнее), но позволяет переименовывать свойства в соответствии с образом ES6.
const pick = (o, ...props) => props.reduce((r, p) => p in o ? {...r, [p]: o[p]} : r, {})
const pick2 = (o, ...props) => props.reduce((r, expr) => {
const [p, np] = expr.split(":").map( e => e.trim() )
return p in o ? {...r, [np || p]: o[p]} : r
}, {})
Вот пример использования:
const d = { a: "1", c: "2" }
console.log(pick(d, "a", "b", "c")) // -> { a: "1", c: "2" }
console.log(pick2(d, "a: x", "b: y", "c")) // -> { x: "1", c: "2" }
Мне потребовалось это разрешение, но я не знал, доступны ли предлагаемые ключи. Итак, я принял @torazaburo ответ и улучшил для моего варианта использования:
function pick(o, ...props) {
return Object.assign({}, ...props.map(prop => {
if (o[prop]) return {[prop]: o[prop]};
}));
}
// Example:
var person = { name: 'John', age: 29 };
var myObj = pick(person, 'name', 'sex'); // { name: 'John' }
Предложение свойств остаточного / расширенного объекта объекта TC39 сделает это довольно гладким:
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
z; // { a: 3, b: 4 }
(У него есть недостаток в создании переменных x
и y
которые вам могут не понадобиться.)
Трюк для решения этого вопроса как однострочного заключается в переводе принятого подхода: вместо того, чтобы начинать с исходного объекта orig
, можно начинать с ключей, которые они хотят извлечь.
Используя Array#reduce
можно сохранить каждый необходимый ключ на пустом объекте, который передается как initialValue
для указанной функции.
Так же:
const orig = {
id: 123456789,
name: 'test',
description: '…',
url: 'https://…',
};
const filtered = ['id', 'name'].reduce((result, key) => { result[key] = orig[key]; return result; }, {});
console.log(filtered); // Object {id: 123456789, name: "test"}
Я не думаю, что есть способ сделать его намного более компактным, чем ваш ответ (или torazburo's), но в основном то, что вы пытаетесь сделать, это эмулировать операцию Underscore pick
. Было бы достаточно легко повторить реализацию в ES6:
function pick(o, ...fields) {
return fields.reduce((a, x) => {
if(o.hasOwnProperty(x)) a[x] = o[x];
return a;
}, {});
}
. Тогда у вас есть удобная функция повторного использования:
var stuff = { name: 'Thing', color: 'blue', age: 17 };
var picked = pick(stuff, 'name', 'age');
pick
один раз, и вы можете выбрать столько свойств, которые хотите, и они не будут удваивать их.
– Ethan Brown
18 September 2014 в 16:58
hasOwnProperty
? Если поля выбраны вручную, даже in
представляется более подходящим; хотя я бы полностью отказался от проверки и просто дал им по умолчанию undefined
.
– Bergi
24 November 2015 в 01:19
Маленькое более короткое решение с использованием оператора запятой:
const pick = (O, ...K) => K.reduce((o, k) => (o[k]=O[k], o), {})
pick
в этом потоке: pick({ name: 'John', age: 29, height: 198 }, 'name', 'age')
– shesek
11 January 2018 в 16:38
Object.assign
; es6 похож на рождественскую елку с таким количеством подарков под ней. Я все еще нахожу подарки через несколько месяцев после отпуска – Ethan Brown 27 May 2015 в 20:57filter(...).map(prop => ({[prop]: get(prop)})))
? – Endless 22 November 2017 в 04:20pick()
вы также можете сделать что-то вродеreturn props.reduce((r, prop) => (r[prop] = o[prop], r), {})
– Patrick Roberts 31 January 2018 в 20:47