【问题标题】:dot notation , window object and its properties点表示法、窗口对象及其属性
【发布时间】:2014-12-09 07:42:04
【问题描述】:

我正在尝试学习一些关于 javascript 的新概念。这是我编写的一个简单代码。在函数内部,这个关键字指的是全局对象,它是窗口,除非它与另一个对象的上下文绑定。在myobj 对象内部,有两个方法与另外两个可全局访问的函数共享相同的名称,分别称为afuncanotherfunc。我想在 myobj 上下文中访问这些全局函数,当然不使用将全局对象绑定到我曾经调用它们的立即调用函数。但它抛出了一个错误。 我的问题是,如果 javascript 中的所有内容都是一个对象,而 window 对象包含它们,那么为什么我可以使用 this.afucnwindow.afunc 访问这些函数?

(function(){
var afunc=function (){
    document.write('this is world'+'</br>');
}
var anotherfunc=function (){
   document.write('this is another world');
}
   var myobj={
       afunc:function(){
	        document.write('afunc');
	   },
	   anotherfunc:function(){
	        document.write('anotherfunc');
	   },
	   context:function(){
	       (function(){
		       this.afunc();
			   this.anotherfunc();
		   })();
	   }
	 };
   myobj.context();
})();

【问题讨论】:

  • 据我所知,JS 中的一切都是对象而不是函数。
  • javascript 中的一切都不是函数,但几乎一切都是对象。基元被包裹在一个临时对象中。您将 myobj 包装在 IIFE 中,这使得 window 对象无法访问它。
  • 并非 JavaScript 中的所有内容都是函数,也并非 JavaScript 中的所有内容都是对象。
  • 几乎一切都是对象。
  • 它们不是全局的,它们是本地你在整个代码周围的函数。把它们移到外面就可以了。

标签: javascript scope this window-object


【解决方案1】:

确实,在您的情况下,this 将引用全局对象,this.afunc() 等将访问全局变量 afunc

但是,除非要显示更多代码,否则您没有全局变量afunc。你定义的变量

(function(){
var afunc=function (){
    document.write('this is world'+'</br>');
}
var anotherfunc=function (){
   document.write('this is another world');
}
//...
})();

是封闭函数的本地(function(){ ... })(); 部分)。

如果你想让它们全局化,你可以将它们移到函数之外:

var afunc = function() {
    document.write('this is world' + '</br>');
};
var anotherfunc = function() {
    document.write('this is another world');
};
(function() {
    var myobj = {
        afunc: function() {
            document.write('afunc');
        },
        anotherfunc: function() {
            document.write('anotherfunc');
        },
        context: function() {
            (function() {
                this.afunc();
                this.anotherfunc();
            })();
        }
    };
    myobj.context();
})();

然而,请注意,在严格模式中,this 将是undefined,而不是指全局对象。这样做是因为通常如果有人在函数中使用this,他们不希望它引用全局对象。仅查看代码,并不总是很清楚您是要访问全局对象(通过this)还是其他对象(正如您所注意到的,您的意图有些混乱)。

这就是为什么,如果你想访问全局对象,你应该明确地这样做并通过window引用它。

【讨论】:

    【解决方案2】:

    首先,我认为你有些事情有点困惑。

    在 JavaScript 中,不是一切都是函数。相反,可以使用一些不同的原语(从 ES5 开始):

    1. 字符串
    2. 号码
    3. 布尔值,
    4. 未定义
    5. 对象

    推荐阅读:Mozilla Documentation on JavaScript Data Structures

    这些类型中的每一种都有与之关联的特殊方法——除了nullundefined,它们是具有非常特定用途的占位符——但这些对于帮助你理解 JavaScript 中发生的事情并不重要. 提供帮助的关键之一是 JavaScript 是一种所谓的函数式语言。在某种程度上,这意味着函数是一流的对象。除此之外,这意味着可以将函数用作值。

    另一件事是,返回的函数并不是唯一返回的东西——函数编程是围绕闭包的思想构建的,或者一个函数以及定义返回函数的范围内的所有相关变量(毕竟,我们可以在返回新函数的函数中引用变量!)

    function foo() {
        var bar = 3;
    
        // Returns a function that when called, returns the Number 5.
        return function () {
            return 1 + 1 + bar;
        }
    }
    

    就缩小错误范围而言,在您的 myObj.context 函数中,我注意到您编写了一个立即调用表达式...

    context: function () {
        (function () {
            this.afunc();
            this.anotherfunc();
        })();
    },
    

    真的有必要吗?事实上,这个功能真的有必要吗?由于我们现在知道 JavaScript 将对象上的函数视为值,因此您始终可以使用 myObj.afuncmyObj.anotherfunc 来处理特定于 myObj 的代码。

    如果您的意图是编写一个方法来调用myObj 上的afuncanotherfunc 方法,那么更好的代码集应该是:

    var myObj = {
        afunc: function () {
            // Magic!
        },
        anotherfunc: function () {
            // More magic!
        },
        context: function () {
            this.afunc();
            this.anotherfunc();
        }
    };
    

    如果您的意图是调用在围绕myObj 声明的立即调用表达式中定义的afunc/anotherfunc,只需从context 中的调用中删除this

    如果您的意图是在全局范围内调用 afunc/anotherfunc 方法,那么您很不幸:您没有在给定的 sn-p 中定义此类函数。但是,这可以像这样修复:

    // Now, afunc exists in the global scope!
    function afunc() {
        // Magic
    }
    
    // Now, anotherfunc exists in the global scope!
    function anotherfunc() {
        // Magic
    }
    
    (function () {
        var myObj = {
            // Your object...
        };
    
        myObj.context();
    })();
    

    不过,一般来说,这被认为是糟糕的编程形式,因为我们用不必要的函数、变量和对象将全局范围弄得一团糟;最好将函数声明保留在立即调用对象中,除非您需要在其他地方调用它们。如果您需要在其他地方调用这些函数,您可能会考虑研究如何执行此操作。

    【讨论】:

    • 仅供参考,原始值不是对象。
    • 嗯,现在更令人困惑了“可以使用几种不同的原语”。 JS中有六种类型。 String、Number、Boolean、Null、Undefined 是基本类型,然后是 Object。一些原始类型(String、Number、Boolean)具有 Object 等价物。函数和数组只是对象。
    【解决方案3】:

    它不起作用,因为this 不是指您认为它指的是什么,而是坚持window。从那里开始,外部的函数并不完全在全局范围内,因为它们被包裹在(function(){ ... })(); 中。现在到您的 context 函数,我们不需要 function() 包装器,因为全局范围内没有任何内容:

       context:function(){
           (function(){ // <-- Here
               this.afunc();
               this.anotherfunc();
           })(); //        <--
       }
    

    删除它(无论如何我们都不想要它),this 将引用 myobj 的实例

       context:function(){
           this.afunc();
           this.anotherfunc();
       }
    

    如果我们想要获得在myobj 范围之外声明的那些,那么您不想使用this。因为这意味着属于myobj 实例的函数。你只想说:

       context:function(){
           afunc();
           anotherfunc();
       }
    

    因为myobj 不知道“全局”函数。

    (function(){
    var afunc=function (){
        document.write('this is world'+'</br>');
    }
    var anotherfunc=function (){
       document.write('this is another world');
    }
       var myobj={
           afunc:function(){
    	        document.write('afunc');
    	   },
    	   anotherfunc:function(){
    	        document.write('anotherfunc');
    	   },
    	   context:function(){
                   afunc();
                   anotherfunc();
    	   }
    	 };
       myobj.context();
    })();

    【讨论】:

    • @Johan this 取决于范围。
    • 这似乎没有回答 OP 的问题。
    • 我想你误解了我的意思。我不想打印 myobj 的方法。我想打印通过调用 myobj 全局声明的 afunc 和 anotehrfunc 函数。
    • @Johan 已修复,抱歉,我注意到它开头没有 $
    • "它坚持 (function(){" 这是什么意思?你是说this 指的是函数本身吗?我可以向你保证事实并非如此。
    猜你喜欢
    • 2021-03-06
    • 2013-09-29
    • 1970-01-01
    • 1970-01-01
    • 2014-06-05
    • 2020-12-14
    • 1970-01-01
    • 2021-12-04
    • 1970-01-01
    相关资源
    最近更新 更多