【问题标题】:javascript functions and objects using keyword 'this' does not work使用关键字“this”的 javascript 函数和对象不起作用
【发布时间】:2013-06-16 12:54:14
【问题描述】:

我的问题是关于 javascript 中的函数和对象。我有三个问题,从一个到另一个。在下面的示例中,我尝试在测试中访问“a”的值,但未定义。但是我创建了一个新的测试对象,然后我可以访问“a”值并对其进行更改。

//create a function called test
         var test=function() {
           this.a=2
           this.b=3 };
           test.a//undefined
//create a object called test1 using 'new'
test1 = new test();
test1.a//2
//change the value of a in test1
test1.a=4
test1 //Object { a=4, b=3}

在试图找出为什么会发生这种情况时,我遇到了这个 javascript functions are objects? 并且从中弹出了另一个问题。 该 SO 问题的公认解决方案如下

var addn = function func(a) {
  return func.n + a;
};

addn['n'] = 3;
addn(3);

我将 'func.n' 更改为 'this',但它不再起作用了

var addn=function func(a) {
 return this.n+a;
};
addn['n']=3;
addn(3); //NaN

使用“this”创建匿名函数也没有帮助

    //anonymous function
var addn=function(a) {
     return this.n+a;
    };
    addn['n']=3;
addn(3); //NaN

为什么使用“this”不起作用?

最后一个问题,使用关键字“new”和“createObject”有什么区别。 Douglas Crokford 在他的书中建议使用“CreateObject”,但我不明白为什么。谢谢大家的cmets

【问题讨论】:

    标签: javascript function object this


    【解决方案1】:

    1。函数是新对象的构造函数

    当您调用new FuncName 时,函数充当构造函数,内部this 的值指向正在构造的对象(而不是函数本身)。当您删除 new 时,this 变为 undefined,回退到全局对象(除非您处于严格模式)。

    2。函数也是对象

    每个函数都是Function 的一个实例,所以函数本身就是对象并且可以有自己的属性。这些属性不能在函数体内使用this.propName 访问,只能使用funcName.propName。那是因为函数中的this从不函数对象本身(除非你强迫它是,bind、call 或 apply)。


    我希望以上两个主题都能帮助您了解函数的工作原理。至于您的最后一个问题:Crockford 的createObject 是实现继承的另一种方式,基本上与Object.create 在符合ES5 的浏览器中所做的一样。它允许一个对象直接从另一个对象继承,而不需要您手动创建一个新的构造函数,设置它的prototype 属性(这是一个函数对象的属性示例),并使用new 创建一个实例。 Crockford 更喜欢这一点,并表示他不再使用 new 来支持这种方法。


    针对您在聊天中提出的问题,这里尝试通过示例来解释什么是函数以及它们的作用。

    函数可以只是...函数

    你打电话给他们,他们做某事:

    function alertThis(what) {
        alert(what)
    }
    alertThis("alerting something");
    

    你也可以给它们传值,让它们返回值

    function timesTwo(num) {
        return num * 2;
    }
    timesTwo(2); // 4
    

    它们可以被传递和返回任何东西,包括对象......

    function createPerson(firstName, lastName) {
        return {
            firstName : firstName,
            lastName : lastName
        }
    }
    var john = createPerson('John', 'Doe');
    john.lastName; // "Doe"
    

    ...和其他功能:

    function timesN(n) {
        return function(num) {
            return n * num;
        }
    }
    var timesThree = timesN(3);
    timesThree(5); // 15
    

    函数是对象

    函数可以像任何普通对象一样被传递和返回。那是因为它们是对象。像任何对象一样,它们可以具有属性:

    function countCalls() {
        countCalls.timesCalled++;
    }
    countCalls.timesCalled = 0;
    countCalls();
    countCalls();
    countCalls.timesCalled; // 2
    

    函数的一个非常重要的默认属性是prototype。这是一个特殊的属性,我们会看到原因。

    函数可以作为新对象的构造函数

    函数的行为类似于常规 OO 语言中的类构造函数。 当使用new 调用时,它们会创建某个“类”的新对象。这个新对象在函数内部被称为this,并自动返回:

    function Person(firstName, lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
    var john = new Person('John', 'Doe');
    john.firstName; // "John"
    john instanceof Person; // true
    

    ...除非你故意返回别的东西:

    function Person(firstName, lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
        var fakePerson = {
            firstName : firstName,
            lastName : lastName
        };
        return fakePerson;
    }
    var notPerson = new Person('John', 'Doe');
    notPerson.firstName; // "John"
    notPerson instanceof Person; // false
    // Note: the object called 'this' inside the function is created, but
    // after the function is called there is no outside reference to it.
    

    构造函数创建的对象知道是谁创建的,并且可以看到它们的prototype属性

    回到真人:

    function Person(firstName, lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
    
    // Add something to the Person prototype
    Person.prototype.sayHi = function() {
        return "hi, I'm " + this.firstName;
    }
    
    var john = new Person('John', 'Doe');
    john.sayHi(); // "Hi, I'm John"
    john.constructor; // Person
    

    对象john 可以sayHi(),因为它可以访问其构造函数的prototype 属性中的所有内容。但是它不能直接看到Person的其他属性(只能通过自己的constructor属性):

    function Person(firstName, lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
        Person.timesCalled++;
        // There is no 'this.timesCalled', only Person.timesCalled
    }
    Person.timesCalled = 0;
    var john = new Person('John', 'Doe');
    john.timesCalled; // undefined - john cannot be called, Person can
    john.constructor.timesCalled; // 1
    

    【讨论】:

    • 感谢 bfavaretto。现在我明白“this”指向正在创建的对象。你能解释一下“当你删除新的,'this'变得未定义......”的意思吗?关于object.create和new,这是否意味着每次使用new构造一个对象时,它的原型都需要初始化,我可以吗?通过将函数方法放在主函数本身中,它不是新构造本身的一部分。?再次感谢
    • 当您调用没有new 的函数时,它不会作为构造函数调用,并且this 不会设置为正在构造的对象(因为没有)。以下代码将创建一个名为bar 的全局变量:function foo(){this.bar = true}; foo();,因为this 将表示全局对象(window)。
    • 使用Object.create或new的区别更多的是与继承有关。 Object.create 只允许您以不那么冗长的方式设置继承(只要您不需要构造函数)。
    • +2:再次感谢您的澄清。在这个例子中,var obj = function() { this.x= 1;返回 { 增量:函数() { this.x = this.x + 1; } } }; var test1=新的 obj(); test1.x //undefined ...但是当我删除 return 语句部分并且只有 var obj = function() { this.x= 1; }; var test1=新的 obj(); test1.x//1...为什么有return语句不允许访问x..
    • @user1988876 因为在这种情况下,构造函数没有返回它正在构造的对象,而是你告诉它返回的新对象;构造函数内的this指的是前者。
    【解决方案2】:

    1。 添加['n'] = 3; //意味着您将静态属性n添加到函数(对象)addn。 所以 addn.n 也可以工作。

    2 this.n 表示实例的属性 n。 this.n === undefined 所以它返回 NaN。

    3 var addn=function func(a) 表示你给 func 取了第二个名字。 var addn=function(a) 在大多数情况下是更好的格式。

    4 createObject 不是原生的 JavaScript 代码。 '新'是。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-04
      • 1970-01-01
      • 2012-11-06
      • 2019-10-10
      • 2018-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多