sourcetip

크롬의 자바스크립트 콘솔은 사물을 평가하는 데 게으른가요?

fileupload 2023. 10. 5. 23:27
반응형

크롬의 자바스크립트 콘솔은 사물을 평가하는 데 게으른가요?

코드부터 말씀드리겠습니다.

var s = ["hi"];
console.log(s);
s[0] = "bye";
console.log(s);

간단하죠?이에 대해 Firefox 콘솔은 다음과 같이 말합니다.

[ "hi" ]
[ "bye" ]

훌륭하지만 Chrome의 JavaScript 콘솔(7.0.517.41 베타)은 다음과 같이 말합니다.

[ "bye" ]
[ "bye" ]

제가 뭔가 잘못한 게 있나요, 아니면 Chrome의 JavaScript 콘솔이 제 배열을 평가하는 데 특별히 게을리 하고 있나요?

Screenshot of the console exhibiting the described behavior.

댓글 달아줘서 고마워요, 기술자.저는 이 문제를 설명하는 기존의 확인되지 않은 웹킷 버그를 찾을 수 있었습니다: https://bugs.webkit.org/show_bug.cgi?id=35801 (편집: 이제 수정되었습니다!)

그것이 얼마나 많은 버그인지와 그것이 고칠 수 있는지에 대해서는 약간의 논쟁이 있는 것 같습니다.제가 보기에는 나쁜 행동으로 보입니다.특히 Chrome에서는 (페이지가 로드되기 전에) 즉시 실행되는 스크립트에 코드가 상주할 때, 콘솔이 열려 있을 때에도 페이지가 새로 고쳐질 때마다 코드가 발생하기 때문에 특히 문제가 되었습니다.콘솔이 아직 활성화되지 않은 상태에서 console.log를 호출하면 대기 중인 개체에 대한 참조만 발생하며 콘솔에 포함되는 출력은 발생하지 않습니다.따라서 콘솔이 준비될 때까지 배열(또는 임의의 개체)을 평가하지 않습니다.이것은 정말 게으른 평가의 사례입니다.

그러나 코드에는 이를 피할 수 있는 간단한 방법이 있습니다.

var s = ["hi"];
console.log(s.toString());
s[0] = "bye";
console.log(s.toString());

String을 호출하면 다음 문장에 의해 변경되지 않는 표현을 메모리에 생성하고 콘솔은 준비가 되면 이 표현을 읽습니다.콘솔 출력은 개체를 직접 전달하는 것과는 약간 다르지만 허용 가능한 것으로 보입니다.

hi
bye

에릭의 설명에 의하면, 그것은console.log()대기열에 있고 배열(또는 개체)의 나중 값을 인쇄합니다.

다음과 같은 5가지 솔루션이 있습니다.

1. arr.toString()   // not well for [1,[2,3]] as it shows 1,2,3
2. arr.join()       // same as above
3. arr.slice(0)     // a new array is created, but if arr is [1, 2, arr2, 3] 
                    //   and arr2 changes, then later value might be shown
4. arr.concat()     // a new array is created, but same issue as slice(0)
5. JSON.stringify(arr)  // works well as it takes a snapshot of the whole array 
                        //   or object, and the format shows the exact structure

다음을 사용하여 어레이를 복제할 수 있습니다.Array#slice:

console.log(s); // ["bye"], i.e. incorrect
console.log(s.slice()); // ["hi"], i.e. correct

대신 사용할 수 있는 기능.console.log이 문제가 없는 경우는 다음과 같습니다.

console.logShallowCopy = function () {
    function slicedIfArray(arg) {
        return Array.isArray(arg) ? arg.slice() : arg;
    }

    var argsSnapshot = Array.prototype.map.call(arguments, slicedIfArray);
    return console.log.apply(console, argsSnapshot);
};

개체의 경우 유감스럽게도 가장 좋은 방법은 웹킷이 아닌 브라우저로 먼저 디버그하거나 복제할 복잡한 함수를 작성하는 것으로 보입니다.키의 순서가 중요하지 않고 기능이 없는 단순한 개체로만 작업하는 경우 항상 다음 작업을 수행할 수 있습니다.

console.logSanitizedCopy = function () {
    var args = Array.prototype.slice.call(arguments);
    var sanitizedArgs = JSON.parse(JSON.stringify(args));

    return console.log.apply(console, sanitizedArgs);
};

이 모든 방법은 분명히 매우 느리기 때문에 일반적인 방법보다 훨씬 더 느립니다.console.log

이것은 웹킷에서 패치되었지만 반응 프레임워크를 사용할 때 어떤 상황에서는 이런 일이 발생합니다. 만약 그런 문제가 있다면 다른 사람들이 제안하는 대로 사용하십시오.

console.log(JSON.stringify(the_array));

Chrome이 "사전 컴파일" 단계에서 "s" 인스턴스를 실제 배열에 대한 포인터로 대체하는 것 같습니다.

어레이를 복제하고 대신 새 복사본을 기록하는 것도 한 방법입니다.

var s = ["hi"];
console.log(CloneArray(s));
s[0] = "bye";
console.log(CloneArray(s));

function CloneArray(array)
{
    var clone = new Array();
    for (var i = 0; i < array.length; i++)
        clone[clone.length] = array[i];
    return clone;
}

지금까지 가장 짧은 해결책은 array 또는 object spread 구문을 사용하여 로깅 시와 같이 보존할 값의 클론을 얻는 것입니다.

console.log({...myObject});
console.log([...myArray]);

그러나 얕은 복사를 수행하므로 주의하십시오. 따라서 심층 중첩된 비 primitive 값은 복제되지 않으므로 콘솔에서 해당 값이 수정된 상태로 표시됩니다.

이것은 이미 답변이 되었지만, 어쨌든 답변을 생략하겠습니다.저는 이 문제를 겪지 않는 간단한 콘솔 포장지를 구현했습니다.jQuery가 필요합니다.

합니다.log,warn그리고.error은 그것이 인 methods,입니다와 를 더 해야 할 입니다.console.

var fixedConsole;
(function($) {
    var _freezeOne = function(arg) {
        if (typeof arg === 'object') {
            return $.extend(true, {}, arg);
        } else {
            return arg;
        }
    };
    var _freezeAll = function(args) {
        var frozen = [];
        for (var i=0; i<args.length; i++) {
            frozen.push(_freezeOne(args[i]));
        }
        return frozen;
    };
    fixedConsole = {
        log: function() { console.log.apply(console, _freezeAll(arguments)); },
        warn: function() { console.warn.apply(console, _freezeAll(arguments)); },
        error: function() { console.error.apply(console, _freezeAll(arguments)); }
    };
})(jQuery);

언급URL : https://stackoverflow.com/questions/4057440/is-chrome-s-javascript-console-lazy-about-evaluating-objects

반응형