Objects and functions in javascript [duplicate]

2019-01-17 21:38发布

Possible Duplicate:
Javascript: Do I need to put this.var for every variable in an object?

I'm struggling to understand functions and objects in javascript. It is said that also functions are objects and objects are kind of "associative arrays" i.e. collections of key-value pairs. I understand that if I write

function myFunction() {
    var value = 0;
}
alert(myFunction.value); //then this gives me "undefined"

because variables have function scope. But if I write

function myFunction() {
    this.value = 0;
}
alert(myFunction.value); //then this gives me "undefined" too.

But finally, If I write

function myFunction() {
    this.value = 0;
}
myFunction.value = 0;
alert(myFunction.value); //then this gives me 0

So I can give myFunction property "value" but from "outside". Can someone explain what is going on and why this.value = 0; doesnt create property "value".

6条回答
The star\"
2楼-- · 2019-01-17 22:15

You need to create a instance by using the new keyword.

function myFunction() {
    this.value = 0;
}

var inst1 = new myFunction();

alert(inst1.value);  // this works

Now this corresponds to the current object , and it gets you the corresponding value of the property.

Check Fiddle

At end of the day .. functions are still objects.. So it does not complain when you assign myFunction.value = 0 .. It might be confusing as you are using the value (key) both inside and outside the function.. Replace it with

myFunction.abc = 'Hello' 
alert(myFunction.abc) still works

But it won't be reflected inside the actual myFunction as you have not called the function yet.

查看更多
欢心
3楼-- · 2019-01-17 22:15

In javascript, any function is also an object, they are objects of Function, just as Number, Object, Array

One tricky thing is the new word, then it prefix before a function, it create a new object, and make this keyword pointer to that new object (one more, it assign that function prototype to the new object __ proto __).
In function,

this.value = 0;

would create a new property value to the new object, and assign 0 to it.

If there is no new before function, it's function call, and this will pointer to Window object.

Try to console.dir(this); in the function, you will see the difference.

myFunction.value = 0;

would create property value to myFunction, and assign 0 to it. Because myFunction is just an object (of Function).

查看更多
看我几分像从前
4楼-- · 2019-01-17 22:23

myFunction is a function object. You can pass it around, assigned it to variables, assign properties to it and you can call it.

Assigning properties works like with any other object:

myFunction.value = 0;

But note that at this point, you have not called the function yet, so the code inside the function (var value = 0; or this.value = 0;) was not even executed yet. Consider this:

function someFunction() {
    window.foo = 'foo'; // create a global variable
}

someFunction.bar = 'bar';

console.log(someFunction.bar); // 'bar'
console.log(window.foo); // undefined

someFunction(); // execute the function

console.log(someFunction.bar); // 'bar'
console.log(window.foo); // 'foo'

When you execute the function with myFunction(), only then the local variable is created / a property is set on this. What this refers to depends on how the function is called and is well explained in the MDN documentation. this never refers to the function itself unless you explicitly set it so.

查看更多
干净又极端
5楼-- · 2019-01-17 22:24

Not sure I can clear up all of the nuances for you, but this may shed some light:

function myFunction() {
    this.value = 0;
}
alert( (new myFunction).value);

Using the new keyword creates a new 'instance' of myFunction allowing this to be used to assign a value from inside the function.

查看更多
Summer. ? 凉城
6楼-- · 2019-01-17 22:26

Let's look at all three cases individually:

function myFunction()
{
    var value = 0;
}

Here, you're declaring a variable in the function's scope. Each time the function is called, the variable will be created (and memory will be allocated). When the function returns, the variable goes out of scope - the variable value is flagged and will be GC'ed. The scope can't be accessed from a scope "higher" than this function's scope... if this function defined a function within its scope, that function will have access to the variable value (look into closures for more details). Bottom line: the variable only exists as when the function is called, and won't exist after the function returns.

function myFunction()
{
    this.value = 0;
}

Here, you're defining a function that could be a constructor, a method, an event handler or a combination of all of the above. this is a reference that will point to the context in which the function is called. This contexted is determined "ad hoc" and may vary:

myFunction();// global scope, this points to window
var anObject = {method: myFunction};
anObject.method();//called in the object's context, this points to object
console.log(abObject.value);//logs 0
var instance = new myFunction();//as constructor
console.log(instance.value);//logs 0
document.getElementById('anInputField').onclick = myFunction;//on click, value will be set to 0

In the last case:

function myFunction()
{
    this.value = 0;
}
myFunction.value = 0;

It wouldn't have made any difference if you'd have written this:

function myFunction()
{}
myFunction.value = 0;

Because, as I explained above: this references whatever the context is at the time the function is called. This needn't be myFunction, in fact: more often than not it won't be:

var anObject = {method: myFunction};
myFunction.value = 101;//myFunction.value is changed
anObject.method();
console.log(anObject.value);//0 -> the function still sets the value property to 0

If you want to access a function's properties inside that function, the easiest way is to reference that function like any other object:

function myFunction()
{
    this.value = myFunction.value;
}
myFunction.value = 101;

Caution:
Just a friendly warning: it's not very safe to use this in functions without checking for globals... If a function is called without an explicit context, JS uses the global (window) object by default. This means that every line that assigns a property to whatever object this happens to be pointing too will set a global variable:

function myFunction()
{
    this.foo = 'bar';
}
myFunction();
console.log(window.foo);//logs bar EVIL GLOBAL

A few ways to prevent the global object from being cluttered with globals:

function mySafeFunction()
{
    'use strict';//throws errors, check MDN
    //this defaults to null, instead of window
    impliedGlobal = 'Error';//doesn't work
    this.onGlobal = 'Error';//null.property doesn't work
}
//same goes for constructors, but a more precise check can be used, too (and works on older browsers)
function SafeConstructor()
{
    if (!(this instanceof SafeConstructor))
    {//this doesn't point to SafeConstructor if new keyword wasn't used
        throw new Error('Constructor wasn\'t called with new keyword');
        //or "correct" the error:
        return new SafeConstructor();
    }
    console.log(this);// will always point to the SafeConstructor object
}
查看更多
冷血范
7楼-- · 2019-01-17 22:26

You misunderstood the javascript prototype/object concepts.

For the first example you are right, the variable has a function scope

The second example is wrong. If you want to use a function as 'class' you have to create an object from it

function myFunction() { this.value = 0; }
var test = new myFunction;

only then you can access the 'value' property of it. for every 'new' statement a new object is created.

In third example you add a static property to function which can be accessed without creating an object. Different technique that's

Hope it helped

查看更多
登录 后发表回答