mengapa coffeescript menambahkan fungsi saat memperluas Objek?

Saya mencoba menulis metode pembantu untuk menemukan perpotongan dua hash/Objek seperti ini...

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] }

hasilnya seperti yang saya harapkan/inginkan KECUALI penambahan kunci/nilai 'berpotongan'.

Apa yang kulewatkan di sini?


person Paul    schedule 14.05.2014    source sumber
comment
Jika w = { a: true, b: 3, d: 4}, maka d: undefined muncul di hasilnya.   -  person hpaulj    schedule 16.05.2014


Jawaban (2)


Properti Anda dapat dihitung, itulah mengapa properti tersebut muncul di kedua objek saat Anda mengulanginya.

Solusinya adalah ini:

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

Demonstrasi (dikompilasi sebagai JS)

Namun memodifikasi objek yang bukan milik Anda, terutama Object adalah praktik yang buruk dan dapat menyebabkan banyak masalah tak terduga bagi pembuat kode lainnya. Baca JavaScript yang Dapat Dipelihara: Jangan memodifikasi objek yang bukan milik Anda.

Di sini akan lebih mudah dan lebih bersih untuk mendefinisikan suatu fungsi dengan mengambil dua objek sebagai argumen...

person Denys Séguret    schedule 14.05.2014
comment
Saya mengerti tentang tidak memodifikasi objek yang bukan milik Anda. Kelompok pengembangan kami terus memperdebatkannya. Meski begitu, saya lebih suka sintaks a.intersect(b) daripada intersect(a,b). Untuk mendukung pendapat Anda tentang OYDO - jika saya yang menulisnya intersect = (a,b)-> t={};(t[k] = a[k] for k of b);t saya tidak akan pernah mengajukan pertanyaan itu. mendesah. Terimakasih banyak! - person Paul; 14.05.2014
comment
@Paul Saya harap Anda akhirnya puas untuk tidak memodifikasi prototipe Objek, Array, dan sebagainya. Awalnya terasa pintar tetapi sebenarnya tidak bijaksana. - person Denys Séguret; 14.05.2014
comment
Ada beberapa masalah kompatibilitas browser dengan defineProperty. developer.mozilla.org/en-US/ dokumen/Web/JavaScript/Referensi/ - person hpaulj; 16.05.2014
comment
prototype= intersect adalah enumerable dan writeable (menggunakan opsi defineProperty). - person hpaulj; 16.05.2014

Menambahkan tanda centang 'ownProperty' akan menghapus properti intersect ini

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 }

Jika w memiliki keys yang tidak ada di x, maka akan muncul di hasil dengan nilai undefined.

Fungsi yang lebih kuat dapat dibangun dari underscore

_ = require 'underscore'
_.pick(x, _.keys(w))
person hpaulj    schedule 14.05.2014
comment
Ini memperbaikinya di sini, tetapi masalah memiliki fungsi enumerable pada semua objek akan muncul di tempat lain. - person Denys Séguret; 15.05.2014