Расширение JQuery кажется нарушенным при перемещении в функцию - PullRequest
0 голосов
/ 17 октября 2019

Вопрос: Как расширить объект «на месте», не создавая новую ссылку на объект.

Краткое содержание: JQuery extension делает то, что говорит на банке.

Но если использовать версию jquery.extend, которая возвращает новый объект, то новый объект, ну, в общем, новый объект. Все хорошо, но если я делаю расширение в функции, в которую я передаю ссылку на объект, который будет расширен, исходный объект остается неизменным. Хорошая ловушка ждет неосторожных (меня). Вы знаете, что объекты передаются по ссылке - верно?

Пример кода: скажем, у меня есть объект

myObject = {
    fontFamily : 'Tahoma',
    fontSize: '12',
    color : '000000'
}

и параметры по умолчанию

myDefaults = {
    fontFamily : 'Tahoma',
    fontSize: '15',
    color : 'FF0000',
    weight : 'bold',
    decoration : 'underline'
}

И мой ожидаемый результат:

myObject = {
    fontFamily : 'Tahoma',
    fontSize: '12',
    color : '000000',
    weight : 'bold',
    decoration : 'underline'
}

Так вот код:

var myObject = {
    fontFamily : 'Tahoma',
    fontSize: '12',
    color : '000000'
}

$('#myObjectIn').html(JSON.stringify(myObject));

extenderoony(myObject);

$('#myObjectOut').html(JSON.stringify(myObject));

function extenderoony(obj){

  var myDefaults = {
        fontFamily : 'Tahoma',
        fontSize: '15',
        color : 'FF0000',
        weight : 'bold',
        decoration : 'underline'
    }

  obj = $.extend({}, obj, myDefaults);  // << Changes the object reference of obj to a new object leaving the original object passed in as the parameter unchanged.

  $('#obj').html(JSON.stringify(obj));


}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div >Before the extend func</div>
<div id='myObjectIn'></div>
<hr>
<div >Inside the extend func</div>
<div id='obj'></div>
<hr>
<div >After  the extend func</div>
<div id='myObjectOut'></div>

Мой ответ кажется хакерским - я опубликую его ниже.

Ответы [ 2 ]

0 голосов
/ 17 октября 2019

Расширение параметров до значений по умолчанию заставляет myDefaults принимать значения, которые вы явно указали. Затем расширение myDefaults на параметры заставляет вас обновить исходный переданный объект, а не назначать его совершенно новому объекту.

var myObject = {
    fontFamily : 'Tahoma',
    fontSize: '12',
    color : '000000'
};

function extend ( options ) {
  let myDefaults = {
    fontFamily : 'Tahoma',
    fontSize: '15',
    color : 'FF0000',
    weight : 'bold',
    decoration : 'underline'
  }
  
  let temp = $.extend( myDefaults, options );
  
  $.extend( options, myDefaults );
}

extend( myObject );

let expectedObject = {
  fontFamily : 'Tahoma'
  , fontSize: '12'
  , color : '000000'
  , weight : 'bold'
  , decoration : 'underline'
};

Object.keys( expectedObject ).forEach( key => {
  console.log( `Does ${key} match expected value?`, myObject[ key ] === expectedObject[ key ] );
} );
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Если вы хотите пропустить двойное расширение, вы можете скопировать ключи самостоятельно.

var myObject = {
    fontFamily : 'Tahoma',
    fontSize: '12',
    color : '000000'
};

function extend ( options ) {
  let myDefaults = {
    fontFamily : 'Tahoma',
    fontSize: '15',
    color : 'FF0000',
    weight : 'bold',
    decoration : 'underline'
  }
  
  Object.keys( myDefaults ).forEach( key => {
    if ( options[ key ] === undefined ) options[ key ] = myDefaults[ key ];
  } );
}

extend( myObject );

let expectedObject = {
  fontFamily : 'Tahoma'
  , fontSize: '12'
  , color : '000000'
  , weight : 'bold'
  , decoration : 'underline'
};

Object.keys( expectedObject ).forEach( key => {
  console.log( `Does ${key} match expected value?`, myObject[ key ] === expectedObject[ key ] );
} );
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
0 голосов
/ 17 октября 2019

Вот мой ответ - тот же базовый фрагмент кода, что и вопрос с дополнениями, как прокомментировано.

var myObject = {
    fontFamily : 'Tahoma',
    fontSize: '12',
    color : '000000'
}

$('#myObjectIn').html(JSON.stringify(myObject));


// Attempt #1
// myObject = extenderoony(myObject); // this fails, I think because the param reference overwrites the returned value 

// Attempt 2
var a = extenderoony(myObject);   // introduce the additional variable to receive the object ref
myObject = a;  // And pass this reference on to the original. Phew, hacky.

$('#myObjectOut').html(JSON.stringify(myObject));

function extenderoony(obj){

  var myDefaults = {
        fontFamily : 'Tahoma',
        fontSize: '15',
        color : 'FF0000',
        weight : 'bold',
        decoration : 'underline'
    }

  obj = $.extend({}, obj, myDefaults);  // << Changes the object reference of obj to a new object leaving the original object passed in as the parameter unchanged.

  $('#obj').html(JSON.stringify(obj));

  return obj;  // have to send back the 'new' object reference cos we used that extend format !

}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div >Before the extend func</div>
<div id='myObjectIn'></div>
<hr>
<div >Inside the extend func</div>
<div id='obj'></div>
<hr>
<div >After  the extend func</div>
<div id='myObjectOut'></div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...