JavaSCript示例(Oreilly书)

时间:2013-02-23 07:10:14

标签: javascript this

方法(对象的函数)可以使用“this”关键字引用对象的变量。

函数的属性可以引用函数变量吗?

例如: -

   function foo()
    {
        var x=5;
    }
    foo.help = {o1:x};// o1 is not initialized to x.
//Using o1:this.x also doesn't help. Why? Explain please.

无论如何将o1初始化为x?

例9-1。一个简单的JavaScript类

// range.js: A class representing a range of values.
// This is a factory function that returns a new range object.
function range(from, to) {
// Use the inherit() function to create an object that inherits from the
// prototype object defined below. The prototype object is stored as
// a property of this function, and defines the shared methods (behavior)
// for all range objects.
var r = inherit(range.methods);
// Store the start and end points (state) of this new range object.
// These are noninherited properties that are unique to this object.
r.from = from;
r.to = to;
// Finally return the new object
return r;
}
// This prototype object defines methods inherited by all range objects.
range.methods = {
// Return true if x is in the range, false otherwise
// This method works for textual and Date ranges as well as numeric.
includes: function(x) { return this.from <= x && x <= this.to; },
// Invoke f once for each integer in the range.
// This method works only for numeric ranges.
foreach: function(f) {
for(var x = Math.ceil(this.from); x <= this.to; x++) f(x);
},
// Return a string representation of the range
toString: function() { return "(" + this.from + "..." + this.to + ")"; }
};
// Here are example uses of a range object.
var r = range(1,3); // Create a range object
r.includes(2); // => true: 2 is in the range
r.foreach(console.log); // Prints 1 2 3
console.log(r); // Prints (1...3)

我的理解: 范围是一个带变量from和to的函数。 Range.methods是Range的属性。它在Range()之外定义,但它仍然可以访问和使用(使用this.from和this.to)。怎么样? 谢谢。

2 个答案:

答案 0 :(得分:3)

修改

此答案基于已编辑的问题 - 原始答案位于

之下

你的理解有点倒退 该功能不会像您认为的那样拥有 fromto

如果我以不同的方式构建它,为了获得几乎所有相同的功能,但对于刚接触JS的人来说要容易多了,我会这样写:

// my `makeRange` function makes an object
// then it gives it all of the things a range object needs
// then it returns the new object
var makeRange = function (min, max) {
    // there are cleaner more-compact ways of doing this
    // I'm writing this out in long-form to show you exactly what's going on
    var rangeObject = {};
    rangeObject.from = min;
    rangeObject.to = max;
    rangeObject.includes = includes;
    rangeObject.foreach  = foreach;
    rangeObject.toString = toString;

    return rangeObject;
};

// these are all of the functions inside of `range.methods`
// they don't have to be attached to the function ***AT ALL***, for ***ANY REASON***
// other than the author wanted them to be there for the sake of organization
// Here, I'm just putting them out on their own, for sake of clarity
var includes = function (x) { return this.from <= x && x <= this.to; },
    foreach  = function (func) {
        var min = this.from,
            max = this.to,
            i   = 0;

        for (i = min; i <= max; i += 1) { func(i); }
    },
    toString = function () { return "(" + this.from + "..." + this.to + ")"; };



var range_3_to_5  = makeRange(3,  5),
    range_6_to_12 = makeRange(6, 12);


range_3_to_5.from;         // 3
range_6_to_12.includes(8); // true
range_6_to_12.foreach(function (i) { console.log(i); }); // [logs:] 6,7,8,9,10,11,12

示例中的methods上的range不是该功能的一部分 它们是 赋予对象的方法,因为它们是构造的
在您给出的示例中,这发生在r = inherit(range.methods);调用内部,该代码块中未对此进行解释。

this根本没有提到这个功能 它指的是 最终对象,该方法在调用方法时使用方法

我的range_3_to_5range_6_to_12都使用includes的相同副本 调用range_3_to_5.includes(6);后,this设置为range_3_to_5,然后该函数会使用this.fromthis.to来确定x是否在范围。

这里没有复杂的魔法 我们只是调用一个以特定方式“制造”某些东西的函数,比如工厂装配线,然后将完成的版本传递出来。

它将共享函数附加到装配线上的每个副本,这些共享函数使用this来确定他们当时正在处理的副本。

var car   = { license : "a32 vx98" },
    truck = { license : "vdx 2000" },
    jeep  = { license : "mkv 3a2b" };


var read_license = function () { console.log(this.license); };


car.read_license   = read_license;
truck.read_license = read_license;

car.read_license();   // [logs:] a32 vx98
truck.read_license(); // [logs:] vdx 2000

我甚至可以使用函数的.call.apply方法自行调用该函数来手动设置this

read_license.call(jeep); // [logs:] mkv 3a2b

或使用.bind保存一直使用this的相同值的函数版本。

var read_car_license = read_license.bind(car);

read_car_license();  // a32 vx98

上面的答案


甚至没有远程。

变量存在于它们创建的函数内部:

var myFunction = function () {
    var myValue = 23;
    console.log(myValue);
};


myFunction(); // [log:] 23
console.log(myValue); // undefined

值可以进一步存在于函数内部:

var myFunction = function () {
    var myValue = 23,

        sayValue = function () {
            console.log(myValue);
        };


    sayValue();  // will log 23 when you call `myFunction`
}



myFunction();  // [log:] 23

但是如果你想让你的变量存在于函数的OUTSIDE(而不是更深入的内部),那么你需要将值返回到某个东西,或者直接从函数内部将它设置为某个东西。

var myOutsideValue = 42,

    myFunction = function () {
        var myValue = 23;
        myOutsideValue = myValue;
    };



console.log(myOutsideValue); // 42
myFunction();
console.log(myOutsideValue); // 23

或者返回......

var myReturnedValue = 0,
    myFunction = function () {
        var myValue = 23;
        return myValue;
    };

myReturnedValue = myFunction();
console.log(myReturnedValue); // [log:] 23

或者你可以传入一个数组或对象进行修改:

var myObject = {},

    myFunction = function (obj) {
        var myValue = 23;
        obj.value = myValue;
    };


myFunction(myObject);
console.log(myObject.value);  // [log:] 23

功能 CAN 引用自己。
因为在JavaScript中,函数是对象(并且可以有自己的属性和方法),所以可以像向任何{}对象添加属性一样向它们添加内容。

var myFunc = function () {
    var myValue = 23;
    myFunc.properties = {};
    myFunc.properties.value = myValue;
};


myFunc();
console.log(myFunc.properties.value); // [logs:] 23

这些都与this没有任何关系。

this用于与您正在寻找的相反 当你在一个连接到一个对象的函数内部时,你想要读取其他属性/运行该对象上的其他方法。

var myObject = {
    x : 23,
    y : 42,
    sayX : function () { console.log(this.x); },
    sayY : function () { console.log(this.y); }
};


myObject.sayX(); // [logs:] 23

this用于其他几个方面,但实际上,这是它的主要作用:访问或设置附加函数的对象的值/方法(通过点属性访问{{1或者通过手动设置,使用obj.func() / .call / .apply),其他非常常见的情况是使用.bind关键字创建新对象。

因此,让new工作的方法并不是弄清x,而是将其设置在函数内部,或者更合适地通过this out(返回x)到外面的另一个变量,然后自己设置值。

x

替代:

var foo = function () {
    var x = "x";
    return x;
},


variable;  // === undefined

foo.help = { o1 : 0 };

variable = foo(); // variable === "x"
foo.help.o1 = variable;


// or shorter:  foo.help.o1 = foo();

var help = { o1 : 0 }, foo = function (obj) { var x = "x"; obj.o1 = x; }; foo(help); foo.help = help; 仅适用于函数

this

如果var obj = {}; obj.x = 12; obj.y = this.x + 5; // DOESN'T WORK 在上一个示例中有效,那只是因为它在函数内部使用this,而是指向FUNCTION'S this,而不是this }。如果您正在调用未附加到对象(objobj.func();func.call(obj))的函数,则new_func = func.bind(obj);将指向this

答案 1 :(得分:0)

在上下文foo.help = {o1: x}中,您与x的定义不在同一个词法范围内,foo定义在this.x函数范围内。这也适用于function foo() { var x = 5; this.help = x; } (适用于对象范围)。

{{1}}