Javascript中的原型和范围

时间:2017-10-30 22:11:06

标签: javascript javascript-objects prototype-chain

var Bar = function(a, b) {

    this.b = b - a;
    this.m2 = function() {
        return this.a / b;
    }

}

var Foo = function(a, b) {
    this.a = a;
    this.b = b;
    Bar.prototype.a = a + b;
    Bar.prototype.b = a - b;
    Bar.prototype.m1 = Bar.prototype.m2;
    Bar.prototype.m2 = function() {
        return this.a * a + this.b * b;
    }
}

o1 = new Bar(1, 5);
o2 = new Foo(2, 3);

o4 = new Foo(3, 2);

r1 = o1.m1();

console.log(r1)
console.log(o1.a)
console.log(o1.b)
r1的值似乎是基于o2 Foo对象实例化前提的原型方法,而不是o4 Foo对象。但是,删除o4 Foo对象似乎会阻止整个工作。同样,删除o2也会阻止它工作。

我觉得正确的行为是o4对对象Bar的原型进行修改,这意味着执行o1.m1()返回的值将来自o4 Bar原型。所以,

return this.a * 3 + this.b * 2;

但事实并非如此。正确的解决方案从此返回:     返回this.a * 2 + this.b * 3;

这似乎违反直觉。在这里有什么属性?为什么解决方案(r1 == 22)依赖于o2和o4的实例化?

编辑:r1应该是22.我正在试图弄清楚我需要走哪条路才能达到这个数字。

2 个答案:

答案 0 :(得分:0)

致电new Bar(1, 5)后,o1.b的值将为4o1.m2的值将是该函数,但无关紧要;那是一只红鲱鱼。

致电new Foo(2, 3)后:

  • Bar.prototype.a将为5
  • Bar.prototype.b将为-1(这将永远不会重要)
  • Bar.prototype.m1将是undefined(无关紧要)
  • Bar.prototype.m2将是一个有效的功能:

    function() {
        return this.a * 2 + this.b * 3;
    }
    

ab(与this.athis.b不同)在该函数中“及时冻结”,并且它们永远不会是23

致电new Foo(3, 2)后:

  • Bar.prototype.a将为5
  • Bar.prototype.b将为1(无关紧要)
  • Bar.prototype.m1将是上面的“m2”函数
  • Bar.prototype.m2将使用相同的功能,但本地a为3且b为2(无关紧要)

因此,当调用o1.m1()时,我们正在运行一个将使用以下值的函数:

  • this.a将为5,因为这是Bar原型属性“a”的最近设置值
  • this.b将为4,因为这是第一步中创建的Bar的实例上的“b”属性的值,以及实例属性阴影原型属性

因此在函数中

function() {
  return this.a * 2 + this.b * 3;
}

根据这些值,我们得到5 * 2 + 4 * 3,而22

答案 1 :(得分:0)

该问题调查了JavaScript的多种行为:

  • 对象的局部属性阴影继承了属性,原型链中保存的渲染值不可访问,
  • 嵌套函数创建的闭包使用外部函数变量和创建内部函数时就绪的参数值:嵌套函数的词法记录链对于每个对创建它们的外部函数的调用都是不同的(内部函数)
  • this内部功能的行为和价值。



var Bar = function(a, b) {

    this.b = b - a;
    this.m2 = function() {
        return this.a / b;
    }

}
// every Bar object has a local property b, and method m2
// these are not inherited
// Bar.prototype values for b and m2 will be ignored

var Foo = function(a, b) {
    this.a = a;
    this.b = b;
    Bar.prototype.a = a + b;
    Bar.prototype.b = a - b;
    Bar.prototype.m1 = Bar.prototype.m2;
    Bar.prototype.m2 = function() {
        return this.a * a + this.b * b;
    }
}
// Foo is (nonsense) code that sets Foo object properties a and b
// These are not used by Bar object methods where "this" refers to the Bar object.

// Setting Bar.prototype.b has no affect as discussed under Bar.

// Although Bar.prototype.m2 is never inherited by Bar objects, it is
// a valid place to store a function value. Initially it is undefined.

// After calling Foo once, Bar.prototype.m1 is undefined.
// After calling Foo twice, Bar.prototype.m1 is
//
//    function() { return this.a * a + this.b * b}
//
// Where this.a was calculated in the most recent call to Foo,
// set on Bar.prototype, and inherited by Bar objects,
// this.b is a local property of the Bar object, and
//  a and b are the parameter values of the call to Foo which created
// the anonymous function object currently stored in  Bar.prototype.m1.


o1 = new Bar(1, 5);
//  at this point o1.b is set to 4 and does not change
//  o1.a is not in the inheritance chain and is undefined
//

o2 = new Foo(2, 3);
// at this point o1.a is inherited as 5 and o1.m1 is undefined

o4 = new Foo(3, 2);
// at this point o1.a is again inherited as 5 (the sum of 3+2)
// and o1.m1 is defined

r1 = o1.m1();
//   uses o1.a=5, o1.b=4 and the values of parameter variables a and b
//   held in the closure created by the nested m2 function inside Foo.
//
// the method function is shuffled down before arriving at Bar.prototype.m1,
// where it captures the a and b parameters of the second to last call to Foo,
// which in this example is a=2, b=3

// So the expected value of o1.m1() is
//  o1.a * a + o1.b * b
// =  5  * 2 + 4 * 3
// = 22

console.log(r1)
console.log(o1.a)
console.log(o1.b)