2015-12-09 76 views
2

我發現自己由於異步性而被絆倒了console.log()console.log的非易失性替代品

由此我的意思是傾向於不捕獲變量的值在特定的時間點。

它適用於簡單值,因爲賦值給具有立即值的變量會將變量綁定到全新的對象。

var x = 3; 
console.log(x); //prints 3 
x=4; 

但是,當您開始使用受引用約束的對象時,事情會變得非常直觀。例如

var obj = {x: 3}; 
console.log(x); //prints 4! 
obj.x = 4; 

有一些其他的日誌記錄功能,我可以使用,將提供給我的對象在調用中的我的代碼條款時的狀態?我正在尋找的是或者同步的東西,或者至少看起來是從它產生的結果。

如果它能夠跨平臺工作,我會很高興,但是我很高興能夠獲得一個能夠在Chrome中工作的工具。

+0

'console.log(JSON.stringify(x))'? –

+2

如果'x'不是循環的,並且是可串行化的,那麼@Kyll說的很好。當它不是,你必須即興創作。在這些情況下,'console.log(x);調試器;'可以暫停代碼,以便在值更改之前檢查值。不幸的是,'temp = val; console.log(temp)'不起作用:它不是深層副本,所以如果你改變'val'的屬性,'temp'的屬性也會改變。 – Amadan

+0

我從來不知道調試器! https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/debugger – LukeP

回答

3

按照要求,總結:

對於簡單,serialisable對象,console.log(JSON.stringify(x))效果很好:

var x = { foo: 17, bar: "quux" }; 
 
console.log(JSON.stringify(x)) 
 
// => {"foo":17,"bar":"quux"}

HTML元素,console.log(x.outerHTML)效果很好。

var x = document.getElementsByTagName('p'); 
 
console.log(Array.prototype.map.call(x, function(e) { 
 
    return e.outerHTML; 
 
})); 
 
// => ["<p>foo</p>", "<p id="bar">bar</p>"]
<p>foo</p> 
 
<p id="bar">bar</p>

如果對象不是serialisable,你可能想鑽到他們並提取serialisable部分:

var x = { content: { foo: 17, bar: "quux" } }; 
x.self = x; 
console.log(JSON.stringify(x.content)); 
// => {"foo":17,"bar":"quux"} 

如果沒有這些技巧的運用,則可能需要深入克隆對象(this answer給出了一個非常好的clone功能,我用下面,和許多警告):

function clone(item) { 
 
    if (!item) { return item; } // null, undefined values check 
 

 
    var types = [ Number, String, Boolean ], 
 
     result; 
 

 
    // normalizing primitives if someone did new String('aaa'), or new Number('444'); 
 
    types.forEach(function(type) { 
 
     if (item instanceof type) { 
 
      result = type(item); 
 
     } 
 
    }); 
 

 
    if (typeof result == "undefined") { 
 
     if (Object.prototype.toString.call(item) === "[object Array]") { 
 
      result = []; 
 
      item.forEach(function(child, index, array) { 
 
       result[index] = clone(child); 
 
      }); 
 
     } else if (typeof item == "object") { 
 
      // testing that this is DOM 
 
      if (item.nodeType && typeof item.cloneNode == "function") { 
 
       var result = item.cloneNode(true);  
 
      } else if (!item.prototype) { // check that this is a literal 
 
       if (item instanceof Date) { 
 
        result = new Date(item); 
 
       } else { 
 
        // it is an object literal 
 
        result = {}; 
 
        for (var i in item) { 
 
         result[i] = clone(item[i]); 
 
        } 
 
       } 
 
      } else { 
 
       // depending what you would like here, 
 
       // just keep the reference, or create new object 
 
       if (false && item.constructor) { 
 
        // would not advice to do that, reason? Read below 
 
        result = new item.constructor(); 
 
       } else { 
 
        result = item; 
 
       } 
 
      } 
 
     } else { 
 
      result = item; 
 
     } 
 
    } 
 

 
    return result; 
 
} 
 

 

 
var el = document.querySelector('p'); 
 
x = { el: el, content: { foo: 17, bar: "quux" } }; 
 
console.log("el.attributes[0]: changed", x); 
 
console.log("el.attributes: empty", clone(x)); 
 
el.setAttribute('changed', 'true');
<p>foo</p>

在最壞的情況下,您可以隨時暫停執行:

var el = document.querySelector('p'); 
 
for (var i = 0; i < 1000; i++) { 
 
    el.textContent = "Iteration #" + i; 
 
    // check 458th iteration: 
 
    if (i == 458) { 
 
    console.log("Accurate:", el); 
 
    debugger; 
 
    console.log("Not accurate:", el); 
 
    } 
 
}
<p></p>

+0

您在克隆片段中使用ES5方法,但使用Object.prototype.toString.call(item)===「[object Array]」,爲什麼不'Array.isArray'?如果'item.constructor'是一個'getter',它將被調用,最好使用'Object.getOwnPropertyDescriptor'來獲得'value',這樣'getter'就不會被調用。 – Xotic750

+0

@ Xotic750:不是我的代碼片段;我將源碼鏈接起來。 – Amadan

+0

夠公平的。 :) – Xotic750

2

另一種可能性與JSON或深拷貝連載是使用節點的用於序列化的inspect。我製作了一個端口(inspect-x),它可以在瀏覽器上運行90%(並非所有功能都可以在瀏覽器中運行)。

var inspect = returnExports; 
 
var x = { 
 
    foo: 17, 
 
    bar: 'quux', 
 
    arr: [1,'2', undefined, null, false], 
 
    fum: function blah() {}, 
 
    fee: new ArrayBuffer(4), 
 
    woo: new Date(), 
 
    wee: /match/gi, 
 
    wiz: 1, 
 
    poo: true, 
 
    pee: Object('hi'), 
 
    jqu: $(document.body), 
 
    ppp: document.getElementsByTagName('pre') 
 
}; 
 
document.getElementById('out').appendChild(document.createTextNode(inspect(x, {showHidden: true}))); 
 
console.log(inspect(x, {showHidden: true}));
<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.3.1/es5-shim.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.3.1/es5-sham.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/json3/3.3.2/json3.min.js"></script> 
 
<script src="https://rawgit.com/Xotic750/inspect-x/master/lib/inspect-x.min.js"></script> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> 
 
<pre id="out"></pre>

,你可以比較JSON.stringify

var inspect = returnExports; 
 
var x = { 
 
    foo: 17, 
 
    bar: 'quux', 
 
    arr: [1,'2', undefined, null, false], 
 
    fum: function blah() {}, 
 
    fee: new ArrayBuffer(4), 
 
    woo: new Date(), 
 
    wee: /match/gi, 
 
    wiz: 1, 
 
    poo: true, 
 
    pee: Object('hi'), 
 
    jqu: $(document.body), 
 
    ppp: document.getElementsByTagName('pre') 
 
}; 
 
document.getElementById('out').appendChild(document.createTextNode(JSON.stringify(x, null, 2))); 
 
console.log(JSON.stringify(x, null, 2));
<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.3.1/es5-shim.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.3.1/es5-sham.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/json3/3.3.2/json3.min.js"></script> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> 
 
<pre id="out"></pre>

正如你可以看到inspect給出更多的信息,並且可以配置更大的深度。