2016-08-21 2 views
2

Посмотрите на вызов Stack and Watch, теперь, когда я нажимаю F10, значение линии в «Watch» изменяется как «Object Object», и из-за этого все происходит, я понимаю поток до этого времени, а потом то, что происходит, Чисто. Теперь в палатах, почему код не останавливается на линии 8, даже если я Предоставлять точку останова в строке 8Как рекурсия происходит в этом фрагменте кода?

Image Это вопрос о stackoverflow

Я пытаюсь понять этот фрагмент кода

function assign(obj, prop, value) { 
    if (typeof prop === "string") 
     prop = prop.split("."); 

    if (prop.length > 1) { 
     var e = prop.shift(); 
     assign(obj[e] = 
       Object.prototype.toString.call(obj[e]) === "[object Object]" 
       ? obj[e] 
       : {}, 
       prop, 
       value); 
    } else 
     obj[prop[0]] = value; 
} 

var obj = {}, 
    propName = "foo.bar.foobar"; 

assign(obj, propName, "Value"); 

Как происходит рекурсия, поскольку функция ничего не возвращает? Как значение аргументов во внутреннем вызове, которое изменяется как функция в самом верхнем стеке вызовов (функции назначения), завершено?

Спасибо всем за ответы, но мой точный вопрос: как это происходит в этой конкретной строке (строка 8).

+1

Объекты в javascript передаются по ссылке, а не по значению. Это означает, что когда вы передаете ссылку на объект как аргумент функции, аргумент функции все равно относится к одному и тому же объекту. –

+0

Возможно, полезно пропустить код с помощью отладчика. –

+0

Уже сделано с отладкой, можете ли вы объяснить, как это - Object.prototype.toString.call (obj [e]) - значение в первый раз является «объектным объектом» и почему код не останавливается на внутренний вызов функции, когда функция в старшем стеке вызовов начинает возвращаться, даже если я применил там точку прерывания? –

ответ

2

Object.prototype.toString.call(obj[e]) === "[object Object]" не соответствует действительности. Это всегда "[object Undefined]"

  1. В начале:

    obj:: {} 
    prop:: 'foo.bar.foobar' 
    
  2. Перед первым вызовом от внутренней функции (if):

    obj:: {foo: {}} 
    prop:: ['bar', 'foobar'] 
    
  3. Перед вторым вызовом от внутренней функции (if) :

    obj:: {foo: {bar: {}}} 
    prop:: ['foobar'] 
    
  4. В последнем исполнении, а prop.length не 1 (else - не более рекурсии):

    obj:: {foo: {bar: {foobar: 'Value'}}} 
    prop:: [] 
    

Объекты в JavaScript, всегда передаются как Reference, см комментарий @Tiny Гиганта.

+0

Если я добавлю obj наблюдать и наблюдаю его значение, он изменяется следующим образом ---------------- obj = {}, а затем {foobar: 'Value'}, а затем {bar : {foobar: 'Value'}}, а затем {foo: {bar: {foobar: 'Value'}}}. :(Я не могу понять, как он изменяется от {foobar: 'Value'} до {bar: {foobar: 'Value'}} и т. Д. –

+0

Правильно. На самом деле, obj в часах обновляется, когда рекурсивный вызов Возвращается тоже! Вместо того, чтобы отслеживать в часах, просто поместите console.log() и распечатайте obj там, где вам нужно. – Nabid

1

Object.prototype.toString.call(obj[e]) === "[object Object]" - это просто уродливый способ сказать: «(если) этот объект существует на самом деле ...». Я не буду подробно объяснять, как это работает, потому что это не очень хороший пример, и вы не можете его понять.

Что хочет код, так это возможность добавлять/редактировать свойство объекта. Например:

var person = {name: 'Liana', hair: {color:'red', style:'long'}}; 
assing(person, 'name', 'George'); 

... и т.п. Но что, если вы хотите отредактировать вложенный атрибут, например, цвет волос?

assign(person, 'hair.color', 'brown');

В основном, функция assign вызывается дважды:

  • assign(person, 'hair.color', ...)
  • Это определяет мы редактируем вложенный атрибут (color) внутри hair и она убеждается hair на самом деле существует внутри person.
  • Если нет, то это создает person.hair (Это то, что некрасиво линия о)
  • Затем вызывает assing(person.hair, 'color', 'brown');

Я бы лично написать функцию, как это:

function assign(object, prop, value) { 
    prop = prop.split('.'); 

    if(prop.length > 1) { 
     var first = prop.shift(); 
     prop = prop.join('.'); 
     if(typeof object[first] != 'object') 
      object[first] = {}; 
     assign(object[first], prop, value); 
    } else { 
     object[prop] = value; 
    } 
} 
+0

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

+0

Ответ @Promote Nabid объясняет это лучше меня. Я написал этот код, потому что я думал, что он может помочь вам понять, что делает исходный код. (На самом деле это то же самое, просто написанное более неясным образом) – mauroc8

1

Как происходит рекурсия, так как функция ничего не возвращает ?

Возврат значения для рекурсии не требуется. Здесь условие prop.length > 1 остановит рекурсию после установки значения желаемого свойства

Как значение аргументов во внутреннем вызове изменяющегося как функции в верхней наиболее вызова стеке (из Назначают функции) завершено?

Я не уверен, что вы спрашиваете здесь. Я думаю, что вы спрашиваете об этой линии obj является

assign(obj[e] = 
       Object.prototype.toString.call(obj[e]) === "[object Object]" 
       ? obj[e] 
       : {}, 
       prop, 
       value); 

Этот код проверяет, является ли объект или нет. Если obj не является объектом, то он будет изменен на объект в самом вызове рекурсии.

Смежные вопросы