在javascript中使用IIFE的'this'关键字

时间:2014-10-07 20:56:05

标签: javascript design-patterns

我正在从本书的一个例子中练习java脚本并遇到以下

代码:在这里我学到了这个'这个' javascript中的关键字引用拥有代码的对象,其中'这个'关键字是。

function Vehicle1(theYear, theMake, theModel) {
    var year = theYear;
    var make = theMake;
    var model = theModel;
    this.getYear = function () { return year; };
    this.getMake = function () { return make; };
    this.getModel = function () { return model; };
}

Vehicle1.prototype.getInfo = function () {
    return 'Vehicle1: ' + this.getYear() + ' ' + this.getMake() + ' ' + this.getModel();
}

代码二:我在这里学习使用IIFE(立即调用函数表达式)创建命名空间。

(function () {
    this.myApp = this.myApp || {};
    var ns = this.myApp;

    var vehicleCount = 5;
    var vehicles = new Array();

    ns.Car = function () { };
    ns.Truck = function () { };

    var repair = {
        description: 'changed spark plugs',
        cost: 100
    };
} ());

我应该单独执行上面的代码来理解作者试图解释的概念。但我最终在单个文件中执行这两个代码,我在第一个代码中收到错误消息

  

未捕获的TypeError:undefined不是函数Vehicle1.getInfo.myApp

问题是:IIFE函数为什么或如何尝试在代码1中放置或查找myApp命名空间?

如果我单独执行2个以上代码,则所有代码都按预期工作。

修改 这是完整的代码,只需使用脚本标记在html的主题部分中复制它。我在chrome中运行它并在控制台中查找错误详细信息

function Vehicle1(theYear, theMake, theModel) {
        var year = theYear;
        var make = theMake;
        var model = theModel;
        this.getYear = function () { return year; };
        this.getMake = function () { return make; };
        this.getModel = function () { return model; };
    };

    Vehicle1.prototype.getInfo = function () {
        return 'Vehicle1: ' + this.getYear() + ' ' + this.getMake() + ' ' + this.getModel();
    }


    (function () {
        this.myApp = this.myApp || {};
        var ns = this.myApp;

        var vehicleCount = 5;
        var vehicles = new Array();

        ns.Car = function () { };
        ns.Truck = function () { };

        var repair = {
            description: 'changed spark plugs',
            cost: 100
        };
    } ());

3 个答案:

答案 0 :(得分:4)

  

我学到了这个' javascript中的关键字引用拥有代码的对象,其中'这个'关键字是。

事实并非如此,但似乎有点像。

警告 - 以下内容听起来很愚蠢。这是因为javascript this是一个非常糟糕的语言功能(人们应该停止使用它)。

这是交易 - 这里并不是this。至少不是你认为的那样。它真的是一个函数参数,就像其他任何函数一样。

让我告诉你。

让我们说你有这样的功能

function sayHi(firstName, lastName) {
    console.log("Hi", firstName, " ", lastName);
}

这里有两种不同但非常相同的方式来调用它:

sayHi("Fred", "Flintstone");
sayHi.call(null, "Fred", "Flintstone");

这是因为所有函数都有call方法。如果您愿意,可以使用.call编写所有函数调用。

但首先null参数是什么?那么,该参数是this将被设置的参数。所以如果你有:

function sayHi(lastName) {
    console.log("Hi", this, " ", lastName);
}
你可以说

sayHi.call("Fred", "Flintstone");

现在让我问你一个问题。如果您始终可以使用.call编写所有函数,并且.callthis作为参数紧挨着其他参数,那么this与其他任何参数的确切区别是什么?只是一个你不知名的人。

sayHi(...)格式对this的影响是什么呢?由于我们没有直接指定它,它必须来自某个地方。好吧,在这种形式 - 这实际上只是call的外观 - javascript 猜测你希望它是什么。这些规则并不复杂,但它仍然令人困惑。

如果您将其作为对象调用

var fred = "Fred";
fred.sayHi = sayHi;
fred.sayHi("Flintstone");

相当于

fred.sayHi.call(fred, "Flintstone");

在直接调用它的情况下:

sayHi("Flintstone");

规则规定它会猜测this是全局window对象。除非你处于严格模式,否则它将是undefined(我认为,它可能是null)。

sayHi.call(window, "Flintstone");

这是IIFE正在发生的事情。

基本上,this是一个强大的功能,使其看起来更像Java,而且根本不需要语言。有些图书馆使用它,而你却没有选择权,但我总是向人们咨询当他们完全控制它时{。}}。

答案 1 :(得分:2)

JavaScript中的this关键字是调用或执行函数的任何内容。在您的示例中,对于IIFE,this将是全局Window对象AKA window

您的问题似乎缺少代码。 CarTruck是否应该延长Vehicle1或其他内容?

你没有调用Vehicle1.getInfo.myApp的代码,所以我不确定你是如何得到这条消息的。

答案 2 :(得分:2)

由于第一个代码后面缺少分号,导致组合文件以与预期不同的方式解释,因此出现错误。

让我们简化代码以查看结构。你有类似的东西:

getInfo = function () {
    this.getYear();
}

(function () {
    this.myApp = {};
} ());

在第一个函数之后没有分号,第二个函数周围的括号被视为给出调用第一个函数的参数:

getInfo = function () {
    this.getYear();
}(function () {
    this.myApp = {};
} ());

所以它基本上就像你写的那样:

function getInfo() {
    this.getYear();
}

getInfo(function () {
    this.myApp = {};
}());
在这两种情况下,

this都指向Window(或全局对象),因为该函数未在实例上调用。您正在调用第二个函数,它将设置Window.myApp,然后将其返回值(未定义)传递给getInfogetInfo将访问不存在的this.getYear,因此您会收到类型错误。

我在这里得到的错误以及原始代码是:

  

TypeError:this.getYear不是函数

因为this是全局对象,所以this.getYear将是未定义的(不是函数)。