Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
272 views
in Technique[技术] by (71.8m points)

javascript functions and objects using keyword 'this' does not work

my question here is about functions and objects in javascript. I have three questions that stems from one to other. In the below example, I try to access the value of 'a' in test, but I get undefined. but I create a new object of test, then I am able to access the 'a' value and change it.

//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}

while trying to find why this happens, I came across this javascript functions are objects? and another question popped out of this. The accepted solution for that SO question is below

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

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

I changed the 'func.n' to 'this' and it no longer works

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

making anonymous function with 'this' also did not help

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

why using 'this' did not work?

one final question, what is the difference in using keyword 'new' and 'createObject'. Douglas Crokford suggests using 'CreateObject' in his book, but I fail to understand why. Thanks all for your comments

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

1. Functions are constructors for new objects

When you call new FuncName, the function acts as a constructor, and the value of this inside points to the object being constructed (not the function itself). When you remove new, this becomes undefined, falling back to the global object (unless you're in strict mode).

2. Functions are also objects

Every function is an instance of Function, so the functions themselves are objects and can have have their own properties. Those properties cannot be accessed with this.propName inside the function body, only with funcName.propName. That's because this inside a function is never the function object itself (unless you forced it to be, with bind, call, or apply).


I hope both topics above help you understand how functions work. As for your final question: Crockford's createObject is a different way to implement inheritance, doing basically what Object.create does in ES5-compliant browsers. It allows an object to inherit straight from another object, without requiring you to manually create a new constructor, set its prototype property (which is an example of a property on a function object), and create an instance with new. Crockford prefers that, and said he stopped using new in favor of this approach.


In response to the questions you asked in chat, here is an attempt to explain what functions are and what they do, with examples.

Functions can be just... functions

You call them, they do something:

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

You can also pass them values, and have them return values

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

They can be passed and return anything, including objects...

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

...and other functions:

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

Functions are objects

Functions can be passed around and returned like any ordinary object. That's because they are objects. Like any object, they can have properties:

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

One very important default property of functions is prototype. It's a special property, and we'll see why.

Functions can act as constructors for new objects

Functions can behave like class constructors do in regular OO languages. When called with new, they create a new object of a certain "class". This new object is called this inside the function, and is automatically returned:

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

... unless you deliberately return something else:

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.

Objects created by constructors know who created them, and can see their prototype property

Back to a real person:

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

The object john can sayHi() because it has access to everything inside its constructor's prototype property. But it cannot see other properties of Person directly (only through their own constructor property):

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...