เหตุใด Coffeescript จึงเพิ่มฟังก์ชันเมื่อขยาย Object

ฉันกำลังพยายามเขียนวิธีการช่วยเหลือเพื่อค้นหาจุดตัดของแฮช/วัตถุสองตัวเช่นนี้...

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