почему функция добавления coffeescript при расширении объекта?

Я пытаюсь написать вспомогательный метод, чтобы найти пересечение двух хэшей/объектов, подобных этому...

Object::intersect = (obj)->
  t = {}
  t[k] = @[k] for k of obj 
  t

x = { a: 1, b: 2, c: 3 }
w = { a: true, b: 3 }
x.intersect(w) #=> { a: 1, b: 2, intersect: [Function] }

результаты такие, как я ожидал / хотел, ЗА ИСКЛЮЧЕНИЕМ добавления ключа / значения «пересечения».

Что мне здесь не хватает?


person Paul    schedule 14.05.2014    source источник
comment
Если w = { a: true, b: 3, d: 4}, то в результате появится d: undefined.   -  person hpaulj    schedule 16.05.2014


Ответы (2)


Ваше свойство перечислимо, поэтому оно появляется в обоих объектах при повторении.

Решение будет таким:

Object.defineProperty Object.prototype, 'intersect', value:(obj)->
  t = {}
  t[k] = @[k] for k of obj
  t

Демонстрация (скомпилировано как JS)

Но изменение объектов, которыми вы не владеете, особенно Object, является ужасной практикой и может привести к множеству неожиданных проблем для других программистов. Прочитайте Поддерживаемый JavaScript: Не изменяйте объекты, которыми вы не владеете.

Здесь было бы так же просто и намного чище просто определить функцию, принимающую два объекта в качестве аргументов...

person Denys Séguret    schedule 14.05.2014
comment
Я понимаю, что нельзя изменять объекты, которыми вы не владеете. Наша группа разработчиков продолжает обсуждать это. Тем не менее, я предпочитаю синтаксис a.intersect(b), а не intersect(a,b). В поддержку вашей точки зрения по поводу OYDO - если бы я написал это intersect = (a,b)-> t={};(t[k] = a[k] for k of b);t, я бы никогда не поднял этот вопрос. вздох. Большое спасибо! - person Paul; 14.05.2014
comment
@Paul Я надеюсь, что вы, наконец, согласитесь не изменять прототип Object, Array и так далее. Сначала это кажется умным, но на самом деле это не так. - person Denys Séguret; 14.05.2014
comment
Есть некоторые проблемы с совместимостью браузера с defineProperty. developer.mozilla.org/en-US/ документы/Интернет/JavaScript/Справочник/ - person hpaulj; 16.05.2014
comment
prototype= intersect является одновременно enumerable и writeable (используя опции defineProperty). - person hpaulj; 16.05.2014

Добавление проверки ownProperty удаляет это свойство intersect.

Object::intersect= (obj) ->
  t = {}
  t[k] = @[k] for own k of obj
  t

coffee> x = {a:1, b:2, c:3}; w = {a:true, b:3}
{ a: true, b: 3 }
coffee> x.intersect(w)
{ a: 1, b: 2 }

Если в w есть keys, которых нет в x, они появятся в результате со значением undefined.

Более надежная функция может быть построена из underscore

_ = require 'underscore'
_.pick(x, _.keys(w))
person hpaulj    schedule 14.05.2014
comment
Это исправляет это здесь, но проблема наличия перечислимой функции для всех объектов будет присутствовать в другом месте. - person Denys Séguret; 15.05.2014