具有尚未定义的属性的窗口,这些属性被定义为未定义

时间:2016-05-22 00:45:54

标签: javascript

所以,我正在编写一个函数,在调用函数时确定起始window和新window之间的差异。但是,没有记录任何内容:

var differences = (function() {
    var original = {};
    for (var i in window) {
        if (window.hasOwnProperty(i)) {
            original[i] = window[i];
        }
    }

    // this is the area I refer to further down in my post

    return function() {
        // should find differences between original and new window
        for (var i in window) {
            if (!(original.hasOwnProperty(i)) && window.hasOwnProperty(i)) {
                console.log(i + ": " + window[i]);
            }
        }
    };
})();

var abc = 5;
differences(); // nothing is logged

所以,我决定检查原始副本中的abc

// after first for loop in foo differences function
console.log(original.hasOwnProperty("abc")); // true
console.log(original.abc);
// this logs that abc is defined as undefined

有人会认为,因为首先定义differences,所以abc对象中不应存在original。但是,因为它确实存在于original对象中,为什么它被定义为undefined而不是5?

但是,让我更加困惑的是我写的hasOwnProperty

console.log(original.hasOwnProperty("abc"));

在JSFiddle中运行时会记录false,但是如果我用JS创建一个空白的HTML文件,它会记录true

有人可以解释这些奇怪的事件吗?

2 个答案:

答案 0 :(得分:1)

当您使用var声明变量时,会在执行任何代码之前将其添加到最直接的execution context (这称为吊装顺便说一句,如果你想搜索主题)

想象一下以下

function foo() {
  // note that the following doesn't throw an error
  console.log(bar)   // undefined
  var bar = 5
  console.log(bar)   // 5
}
foo()
console.log(bar)   // throw an error

调用该函数时,内部会发生以下步骤

  • 创建执行上下文
  • 所有函数/变量声明都在执行上下文中定义
  • 执行代码

如果变量是在函数外定义的,那么它最直接的执行上下文就是全局上下文,在Web浏览器中是window对象

  // note that the following doesn't throw an error
  console.log(bar)          // undefined
  console.log(window.bar)   // undefined      
  console.log(window.hasOwnProperty('bar'))   // true
  var bar = 5
  console.log(bar)   // 5
  console.log(window.bar)   // 5
  

但是,更令我困惑的是我写的hasOwnProperty行   console.log(original.hasOwnProperty("abc"));   在JSFiddle中运行时,它会记录为false,但如果我使用JS创建一个空白的HTML文件,则会记录为真。

     

有人可以解释这些奇怪的事件吗?

JSFiddle的问题是不是代码是在iframe上运行,如果你检查由iffe创建的iframe,那么你编写的代码会被JSFiddle放入一个函数中JSFiddle你会看到以下



<html>
  <head>
  <script>
//<![CDATA[
window.onload=function(){
console.log(window.hasOwnProperty('bar'))  // false
var bar = 5
}//]]> 
  </script>
  </head>
  <body>
  </body>
</html>
&#13;
&#13;
&#13;

但是,如果您的代码位于script标记内或外部脚本中,就像使用空白html一样,您将得到以下内容

&#13;
&#13;
console.log(window.hasOwnProperty('bar'))  // true
var bar = 5
&#13;
&#13;
&#13;

答案 1 :(得分:0)

尝试创建一个IIFE,其中original传递给包含要调用的函数的对象。请注意,!(original.hasOwnProperty(i))将返回falseconsole.log(i + ": " + window[i])将不会在第二个for循环中调用,因为window的属性之前已设置为original

您可以在第!个循环内的if条件下移除for运算符,在对象返回的调用函数可以查看console.log(i + ": " + window[i])的结果;返回original作为同一对象的属性值,以确定abcoriginal

是否定义了window
var differences = (function() {
    var original = {};
    for (var i in window) {
        if (window.hasOwnProperty(i)) {
            original[i] = window[i];
        }
    }

    // this is the area I refer to further down in my post  
    return {
        props: function() {
            return (function(original) {
                // should find differences between original and new window
                for (var i in window) {
                    if ((original.hasOwnProperty(i)) && window.hasOwnProperty(i)) {
                        console.log(i + ": " + window[i]);
                    }
                }
                ;
            }(original)) 
        },
        o: original
    };
})();

var abc = 5;
var diff = differences;
diff.props();
console.log(window["abc"], diff.o["abc"])