Bir DOM nesnesi üzerinde bir özellik ayarlarken parametrenin yeniden atanmaması nasıl önlenir


98

Ana amacı bir DOM nesnesi üzerinde bir özellik ayarlamak olan bir yöntemim var

function (el) {
  el.expando = {};
}

AirBnB'nin ESLint'in bir no-param-reassignhata atmasına neden olan kod stilini kullanıyorum :

error 'el' no-param-reassign fonksiyon parametresine atama

AirBnB'nin kod stilini uygularken bağımsız değişken olarak iletilen bir DOM nesnesini nasıl değiştirebilirim?

Birisi başka bir soruna/* eslint react/prop-types: 0 */ atıfta bulunmayı önerdi, ancak yanılmıyorsam bu tepki için iyi, ancak yerel DOM manipülasyonu için geçerli değil.

Ayrıca kod stilini değiştirmenin bir cevap olduğunu düşünmüyorum. Standart bir stil kullanmanın faydalarından birinin projeler arasında tutarlı koda sahip olmak olduğuna inanıyorum ve kuralları istediğiniz zaman değiştirmek AirBnB'ler gibi büyük bir kod stilinin kötüye kullanılması gibi geliyor.

Kayıt için GitHub'da AirBnB'ye, 766 numaralı sayıdaki bu durumlarda gitmenin yolunun ne olduğunu sordum .


Hayır. İlk olarak, bu, kuralın mantıklı olduğu diğer tüm olaylar için bunu devre dışı bırakmak anlamına gelir. İkincisi, bir stil rehberini takip edip etmediğinize inanıyorum. En azından, her tür projede birçok geliştiricinin izlediği bir stil rehberi ise.
Lukas

2
Ama nasıl soruyorsunuz değil bunu engellemeye çalışıyor şeyi yapıyorlar çünkü, Stil Kılavuzu itaat etmek. Her durumda, bu işlev için devre dışı
bırakmanız yeterlidir


@Matleti Bunu kurallara uyarak yapmanın bir yolu olup olmadığını merak ediyordum.
Lukas

Nasıl söylerseniz söyleyin, istediğiniz işlem kuralla çelişir. Bununla birlikte, bir XY problemi gibi görünüyor; Özellikleri doğrudan bu şekilde DOM düğümlerine eklemem.
Matematik

Yanıtlar:


103

@Mathletics'in önerdiği gibi, bunu dosyanıza ekleyerek kuralı tamamen devre dışı bırakabilirsiniz.eslintrc.json :

"rules": {
  "no-param-reassign": 0
}

Ya da kuralı özellikle param özellikleri için devre dışı bırakabilirsiniz

"rules": {
  "no-param-reassign": [2, { "props": false }]
}

Alternatif olarak, o işlev için kuralı devre dışı bırakabilirsiniz

/* eslint-disable no-param-reassign */
function (el) {
  el.expando = {};
}
/* eslint-enable no-param-reassign */

Veya sadece bu satır için

function (el) {
  el.expando = {}; // eslint-disable-line no-param-reassign
}

Ayrıca , özellikle AirBnB'nin stil kılavuzuna uyum sağlamak için ESLint kurallarını devre dışı bırakma hakkındaki bu blog gönderisine de göz atabilirsiniz .


1
Teşekkür ederim. Görünüşe göre çoğu insan linter'i değiştirmeyi en iyi yol olarak buluyor. Bunu tek bir satır için uygulamak şu anda benim için en iyi takas gibi görünüyor.
Lukas

2
Nodejs değiştirmek isteyebilirsiniz bazen projeler, ifade için Bu gerçekten duyu ie yapmak res.sessionhemen
David

Problem sadece soruda belirtildiği gibi fonksiyon parametrelerinin özelliklerinin ayarlanmasından kaynaklanıyorsa, Gyandeep'in aşağıdaki cevabı çok daha iyidir.
Prashanth Chandra

88

Gibi bu makalede anlatılmaktadır , bu kural mutasyona önlemek içindir argumentsnesneyi . Bir parametreye atarsanız ve daha sonra argumentsnesne aracılığıyla bazı parametrelere erişmeye çalışırsanız , beklenmedik sonuçlara yol açabilir.

DOM öğesine bir referans almak için başka bir değişken kullanarak kuralı olduğu gibi koruyabilir ve AirBnB stilini koruyabilir ve ardından bunu değiştirebilirsiniz:

function (el) {
  var theElement = el;
  theElement.expando = {};
}

(DOM düğümlerinin dahil) JS nesnelerde bu nedenle burada referans olarak geçirilir elve theElementaynı DOM düğüme referanslar, ancak tadil theElementmutasyona etmez argumentsçünkü nesne arguments[0]kalıntıları DOM elemanı için sadece bir referans.

Bu yaklaşım, kuralın belgelerinde belirtilmiştir :

Bu kural için doğru kod örnekleri:

/*eslint no-param-reassign: "error"*/

function foo(bar) {
    var baz = bar;
}

Kişisel olarak, "no-param-reassign": ["error", { "props": false }]bahsedilen yaklaşımı birkaç diğer cevapta kullanırım. Bir parametrenin bir özelliğini değiştirmek, o parametrenin neyi ifade ettiğini değiştirmez ve bu kuralın kaçınmaya çalıştığı sorun türleriyle karşılaşmamalıdır.


6
Bu, davranışı atlatmanın bir yolu değil, kabul edilen cevap olmalıdır. Bu cevap ve Patric Bacon resmi ESLint belgelerinde belirtildiği gibi belirli senaryolarda ortaya çıkabilecek açık bir soruna işaret ettiğinden
Remi

1
Bu cevap, resmi belgelere işaret ettiği ve iyi açıklandığı için kabul edilen cevap olmalıdır. Diğer cevapların çoğu yangın alarmını kapatmak gibidir!
Hamid Parcham

"Yerel değişken 'theElement' gereksizdir" alabilirsiniz.
Phạm Tuấn Anh

Bu yeni referanslar için ne tür bir adlandırma şeması kullanırsınız? Buradaki şeylerin önüne 'My' koymaktan kesinlikle nefret ediyorum, ancak yeni bir referans oluştururken zaten uygun şekilde adlandırılmış parametreleri yeniden adlandırmak gerçekten zor ve hatta sezgiye aykırı.
GhostBytes

Sadece kontrol ettim ve arguments[0]mutasyona uğradım. Neyi yanlış yapıyorum? ... theElement.expando = { p: 2 }; return arguments[0].expando; ....
mrmowji

20

Bu kuralı .eslintrcdosyanızın içinde geçersiz kılabilir ve bunun gibi parametre özellikleri için devre dışı bırakabilirsiniz.

{
    "rules": {
        "no-param-reassign": [2, { 
            "props": false
        }]
    },
    "extends": "eslint-config-airbnb"
}

Bu şekilde kural hala etkindir ancak özellikler için uyarmaz. Daha fazla bilgi: http://eslint.org/docs/rules/no-param-reassign


3
Bu cevap tamamen kabul edilen cevapta yer almıyor mu?
Dan Dascalescu

1
@DanDascalescu Kabul edilen cevabın altında buna işaret eden bir yorum var, yani belki bir noktada daha kapsamlı olması için düzenlenmiş olabilir mi?
bigsee

12

no-param-reassignUyarı ortak fonksiyonlar için mantıklı ama klasik için Array.forEachbunu mutasyona niyetinde dizisi üzerinde döngü uygun kaynaklarına değildir.

Bununla birlikte, bunu Array.mapaşmak için yeni bir nesne ile de kullanabilirsiniz (eğer benim gibiyseniz, uyarıları yorumlarla ertelemekten hoşlanmayın):

someArray = someArray.map((_item) => {
    let item = Object.assign({}, _item); // decouple instance
    item.foo = "bar"; // assign a property
    return item; // replace original with new instance
});

4
function (el) {
  el.setAttribute('expando', {});
}

Diğer her şey sadece çirkin hackler.


2

Bu kuralı seçici olarak devre dışı bırakmak isteyenler, hangi parametre yeniden atamasının göz ardı edilmesi gerektiği ile ilgili olarak nesne adlarının bir "beyaz listesine" izin verecek olan kural için önerilen yeni bir seçenekle ilgilenebilirler no-param-reassign.


Yukarıda, temsilci puanlarının yetersizliği nedeniyle yorum yerine yanıt olarak yayınlanmıştır.
RH Becker




-1

Kullanabilirsiniz:

(param) => {
  const data = Object.assign({}, param);
  data.element = 'some value';
}

1
Bu sadece kopyayı değiştirmiyor mu (bu ne kadar değerli)?
2540625

1
Bu gerçekten bir çözüm değildir, çünkü bu, yeni bir nesne oluşturarak param yeniden atamasından kaçınmak anlamına gelirken, ben açıkça yeni bir nesne oluşturmamalı, orijinali değiştirmem gerekiyor.
Lukas

Parametreleri değiştirmemeyi tercih ederim, ancak bu şekilde yaparsanız, Object.defineProperty () 'yi de kullanabilirsiniz, linter size bir hata vermez.
Oliver

Bu hiç işe yaramaz. Değişkenin bir kopyasını oluşturuyorsunuz, ondan özellikleri yeni bir nesneye kopyalıyorsunuz, bir özelliği değiştiriyorsunuz ve sonra geri döndürmüyorsunuz, böylece hiçbir şey olmuyor. Geri vermiş olsanız bile, iletilen gibi bir DOM öğesini değil, bir nesneyi döndürürsünüz. Bunun da Object.assignötesinde, bir nesneden bir hedef nesneye kopyalamak içindir. Bunun gibi bir DOM öğesinden kopyalamaya çalışmak boş bir nesne ile sonuçlanır.
Yararsız Kod

Ayrıca Object.assign, nesnede bir özelliği döngüsel referanslarla yeniden değerlendirmeye çalışıyorsanız (örneğin bir soket bağlantısı) uygun şekilde çalışmaz. Object.assignvarsayılan olarak sığ bir kopyadır ve derin klonlama, performansın düşmesi nedeniyle çok hoş karşılanmaz.
ILikeTacos

-1

Bir nesne dizisi içindeki herhangi bir değeri değiştirmek istiyorsanız, şunu kullanabilirsiniz:

array.forEach(a => ({ ...a, expando: {} }))
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.