• No se han encontrado resultados

FACTORES QUÍMICOS

In document TERATOGENICIDAD DE ANESTÉSICOS (página 170-180)

ESTUDIO DE LA TERATOLOGÍA

FACTORES QUÍMICOS

You saw an example of using the this keyword when we looked at our static object

in this chapter. We will now spend some time on this to understand what it is and

how it can help us write better code.

The this keyword is simply a reference to an object. However, that reference can

point to different objects at different times, depending on the code execution context. To see what that means, let's start by creating a simple constructor function:

function Person(){ this.name = "Tom";

this.job = "Software Developer"; }

In the preceding code, the this keyword has a global context. So inside the Person

function, this refers to the window object (if the code is run in a browser). In fact, if

we execute the following: Person();

We have now created two properties for the window object, called name and job. We

can prove this by running the following:

console.log(window.name); // displays "Tom";

console.log(window.job); // displays "Software Developer";

Keep in mind that adding properties to the global context (the window object) is not a

good idea and will pollute the global context as well as creating a high possibility of naming collisions. This could result in unexpected behavior in the code and strange bugs that are hard to track.

But the this keyword can take a whole new context and reference a totally different

object, when used as the following:

function CreatePerson(personData){ this.name = personData.Name; this.job = personData.Job;

}

var personOneData = { Name: "Tom",

Job: "Software Developer" };

var firstPerson = new CreatePerson(personOneData); console.log(firstPerson.name);// displays "Tom"

console.log(firstPerson.job); // displays "Software Developer" Here, we are creating a new person object using our CreatePerson constructor.

By using the new keyword, an instance of person is created and the variable firstPerson now holds a reference to this instance. This person instance has its name property set to Tom and its job property to Software Developer.

Note that the this keyword inside this object now refers to the instance.

Let's create another person object definition as below: var personTwoData = {

Name: "John",

Job: "Software Architect" };

And use our constructor function to create an instance of this second person. Once the following code is executed, this will refer to the instance of this second

person.

var secondPerson = new CreatePerson(personTwoData); We can examine the properties of the second person, as follows:

console.log(secondPerson.name); // displays "John";

console.log(secondPerson.job); // displays "Software Architect" Things can get a little more interesting at times and a bit harder to figure out what the context of this can be in different circumstances.

Consider the following example:

var name = "The window global"; var myOwnObject = {

name: "my Own Object", getName: function(){ return this.name; }

};

As you can see in this example, we have defined an object using object literal notation. This object is assigned to the myOwnObject variable and its getName

method returns the value of the name property in the object. So, as you might expect, this in this context refers to the context of myOwnObject:

console.log(myOwnObject.getName()); // displays "my Own Object" However, if we make an assignment such as:

// displays "The Window global"

console.log((myOwnObject.getName = myOwnObject.getName)()); This will produce the result: The window global. This result is rather confusing. When we make the above assignment, only the function gets assigned from the left side of the expression to the right side of the expression and now this refers to the

global object. Note that, in this scenario, myOwnObject.getName is just a function and

as explained before this inside a function (not an instance of an object) always refers

to the global context, which produces the result, The window global, when executed in the browser.

Let's consider another object definition and create an inner function (a Closure, which we will talk about shortly) inside this object. The context of this may not be

what you expect in this scenario. var name = "The window global"; var myOwnObject = {

name: "my Own Object", getName: function(){ return function(){ return this.name; }; } };

Since the innermost function is an anonymous function inside another anonymous function, the context of the innermost function is different from the object that is hosting it. Therefore, this in this context is referencing the global context.

In order to preserve the context of myOwnObject, we can create a context in the first

inner function and let the innermost function access this context. So we can rewrite our object definition as:

var name = "The window global"; var myOwnObject = {

name: "My Own Object", getName: function(){ var that = this; return function(){ return that.name; };

} };

console.log(myOwnObject.getName()()); // displays "My Own Object" Using this approach, we create a context inside the first inner function which references our object and then the innermost function can access this context, which is defined in its container (the first anonymous function). This results in the innermost anonymous function accessing the context of myOwnObject object.

As shown, it can be a little challenging to figure out what context this refers to at

times but with practice and more experience you will become better at it. However, till then, don't take the context of this for granted and make sure that the context which

you think this refers to is in fact the context that has been set for this in the code.

Closures

Now that we have had a brief discussion regarding execution context as it relates to this, it is time to talk about Closures. If you don't have a lot of experience with

JavaScript, or if you are coming from more classical object oriented languages such as C++, you might find the concept of Closures a bit confusing in the beginning. In this section, I will try to take the mystery out of this concept and explain why Closures can be very useful in our code.

The main idea behind Closures is about preserving context and (mostly) how an inner function can keep the context of its containing parent.

Consider the following simple example: function setTestValue(value){ var firstNum = value || 2; return function(secondNum){ if(firstNum > secondNum){ return firstNum;

}else if(firstNum < secondNum){ return secondNum; }else{ return "="; } }; }

var theNumberExaminer = setTestValue(6); var result = theNumberExaminer(2); console.log(result); // displays 6

As you can see, innermost function setTestValue takes a number as a parameter

and sets it as the starting value to be used for comparison later.

When this function is executed, it also returns an anonymous function whose reference will be stored in the theNumberExaminer variable. This anonymous

function is then used to compare a value passed to it with the value that was set as the starting value (firstNum) in the setTestValue function.

Note that we only pass one value (2) to theNumberExaminer to be compared against

the starting number.

The question is: how does theNumberExaminer have access to the previous value

passed to the setTestValue function?

Normally, when a function is returned, its execution context is removed and thus all the values related to that function's execution context are destroyed. However, with Closures, things work a little differently.

Here, the inner anonymous function is returned from the setTestValue function call

(setTestValue(6)) and, with it, the execution context of its parent function. This

allows the anonymous function to have access to the value of firstNum.

This relationship will hold as long as the inner function (the anonymous function) is not destroyed. The context of the parent object remains in memory because there is

The most important point is that Closures allow for inner functions to have access to the execution context of their parent functions (objects) as part of their scope chain. As values in the scope of the outer function change, the inner function can have access to the most recent values.

One advantage of creating and using Closures can be shown in the following example: function myClosedObject (){ var privateValue = 5; function privateFunc (){ privateValue *= 2; return privateValue ; } // privileged method this.publicFunc = function(){ return privateFunc(); }; }

var firstObj = new myClosedObject ();

console.log(firstObj.publicFunc()); // displays 10 console.log(firstObj.publicFunc()); // displays 20

In the preceding code, we first create an instance of myClosedObject and then we

execute the publicFunc of this instance. This call changes the value of privateValue

from 5 to 10.

When we call this method one more time, the value of privateValue will change to 20. This is because after the first call to publicFunc the value of privateValue has

been preserved (thanks to the created Closure). The second call to publicFunc, uses

the most up to date value of privateValue (which is 10) to do its calculation, thus

resulting in the value 20 being returned.

In document TERATOGENICIDAD DE ANESTÉSICOS (página 170-180)

Documento similar