while循环和"this"对象

A while loop and the "this" object

本文关键字:quot 对象 this 循环 while      更新时间:2023-09-26

下面的代码为Object的原型定义了一个自定义方法,该方法使用本机方法"hasOwnProperty"来查找传入属性的所有者。

Object.prototype.findOwnerOfProperty = function(propName){
    var currentObject = this;
    while (currentObject !==null){
        if (currentObject.hasOwnProperty(propName)){
            return currentObject;
        }
    }
}

我遇到的while循环通常是这样的格式:

while ( x < 10 ){
    // do stuff
    x++;
}

假设我在一个对象上调用了"findOwnerOfProperty"方法:

newObject.findOwnerofProperty(firstProp);

我的问题是:

1)当循环运行时,"this"对象发生了什么?

2)循环到底在迭代什么?

3)第一个while循环和第二个while循环之间的区别是什么,第二个循环有一个明显的增量,显式地改变计数器'x',而第一个循环没有?第一部分代码的哪一部分改变了"currentObject"?

第一个while循环和第二个while循环有什么区别

第一个while循环是无限循环,因为currentObject永远不会改变。

属性名首先在对象本身上解析,然后在其[[Prototype]]链上的对象上解析。您可以使用Object访问该链。getPrototypeOf,所以你可以这样做:

Object.prototype.findOwnerOfProperty = function(propName) {
  var obj = this;
  do {
    if (obj.hasOwnProperty(propName)) {
      return obj;
    }
    obj = Object.getPrototypeOf(obj);
  } while (obj)
}
// Some tests
var obj = {foo:'foo'};
var x = obj.findOwnerOfProperty('foo');
console.log(x == obj); // true
// Find foo on Bar.prototype
function Bar(){}
Bar.prototype.foo = 'foo';
var bar = new Bar();
var p = Object.getPrototypeOf(bar);
console.log(bar.findOwnerOfProperty('foo') == Bar.prototype); // true
// Find toString on Object.prototpye
console.log(bar.findOwnerOfProperty('toString') === Object.prototype); // true
// Non-existant property
console.log(bar.fum); // undefined
console.log(bar.findOwnerOfProperty('fum')); // undefined 

如果没有找到这样的对象,上面返回undefined,这似乎是合适的,因为null在所有[[Prototype]]链的末尾,返回null表明在那里找到了该属性。

注意对象。getPrototypeOf是ES5的,所以不是在所有的浏览器中使用。

编辑

函数可能会以this不是Object的值调用,例如:

bar.findOwnerOfProperty.call(null, 'bar');

期望的结果可能是undefined或者可能是类型错误,但是实际结果取决于代码是否严格以及提供的值。

非严格代码 -如果这个是一个原语,那么它将被设置为对原语值应用抽象ToObject操作符的结果(例如,如果它是一个数字,那么有效地new Number(value),如果它是一个字符串,那么new String(value))。

nullundefined的情况下,this被设置为全局对象(注意,将ToObject应用于nullundefined抛出错误),因此将检查错误的继承链(即全局对象,而不是null),并可能返回全局对象。

这两种情况的解决方案是"RTFM"(好吧,如果有的话…),因为在任何代码执行的时候,这个已经设置好了,不可能检查原始调用。

严格代码——在这种情况下,this的值没有被修改,因此可以进行检查以确保它是一个对象或函数,并返回undefined否则:

Object.prototype.findOwnerOfProperty = function(propName) {
  var obj = this;
  // Only applies to strict mode
  if ((typeof obj != 'object' && typeof obj != 'function') || obj === null) return;
  while (obj) {
    if (obj.hasOwnProperty(propName)) {
      return obj;
    }
    obj = Object.getPrototypeOf(obj);
  }
}

所以对于严格模式和非严格模式可能会有不同的结果,例如

bar.findOwnerOfProperty.call(7, 'toString');
对于严格代码

返回undefined,对于非严格代码Number(即Number构造函数)(因为7被new Number(7)转换为Number对象,并且在Number对象上调用typeof返回'object')。

为了达到一致性,对于nullundefined以外的值,可以为严格的代码模拟ToObject操作符。或者,非严格版本只能对typeof返回函数对象的值进行操作。我将把这个决定留给那些真正想在愤怒中实现这个的人。