Object.defineProperty - 范围和使用函数返回对象?

时间:2016-06-28 21:24:43

标签: javascript properties scope

我正在学习JavaScript(在64位Debian Jessie上使用最新的Google Chrome构建版本),现在已经有几天了,现在我仍然在理解Object.defineProperty的确切运作方式。我有以下页面:

function createPerson() {
    var person = {
        firstName: 'Lilly',
        lastName: 'Louis',
    };

    Object.defineProperty(person, 'fullName', {
        get: function() {
            return this.firstName + ' ' + this.lastName;
        },
        set: function(name) {
            var words = name.split(' ');
            this.firstName = words[0] || '';
            this.lastName = words[1] || '';
        }
    });
}

var p1 = createPerson();
console.log("Person's default name is \"" + p1.fullName + "\"");

我在{I}尝试使用Uncaught TypeError: Cannot read property 'fullName' of undefined内的属性的行中得到console.log(...)。如果我将person的定义和Object.defineProperty放在函数外部,一切正常。如果我在Object.defineProperty之后创建了 p1,请执行此操作:

var p1 = createPerson();
Object.defineProperty(p1, 'fullName', {
    get: function() {
        return this.firstName + ' ' + this.lastName;
    },
    set: function(name) {
        var names = name.split(' ');
        this.firstName = names[0] || '';
        this.lastName = names[1] || '';
    }
});

我得到Uncaught TypeError: Object.defineProperty called on non-object,然后控制台指出它是在(anonymous function)(即p1)上调用的,这更加令人困惑,因为我刚才读到了如果我将callPerson分配给我的p1而没有括号我正在将函数对象传递给它,否则我正在调用函数本身并分配其返回值(如果没有, undefined 被退回)p1

我觉得这两个问题完全是分开的,但我仍然不能100%肯定我已经决定将两者放在同一个问题上。我在这里做错了什么建议?我可以通过简单地执行

来定义我的gettersetter旧式方式
function createPerson() {
    var person = {
        firstName: 'Lilly',
        lastName: 'Louis',
        getFullName: function() {
            return ...;
        }
        setFullName: function(name) {
            ...
        }
    };
}

但我想了解这里发生了什么。 :d

2 个答案:

答案 0 :(得分:4)

您的defineProperty电话绝对没问题。问题是createPerson永远不会返回任何内容,因此调用它的结果是undefined。你最后想要return person;



function createPerson() {
  var person = {
    firstName: 'Lilly',
    lastName: 'Louis',
  };

  Object.defineProperty(person, 'fullName', {
    get: function() {
      return this.firstName + ' ' + this.lastName;
    },
    set: function(name) {
      var words = name.split(' ');
      this.firstName = words[0] || '';
      this.lastName = words[1] || '';
    }
  });
  
  return person; // <=======
}

var p1 = createPerson();
console.log("Person's default name is \"" + p1.fullName + "\"");
&#13;
&#13;
&#13;

或者,将其设为构造函数函数(与new一起使用)而不是工厂函数,并在函数中使用this。在这种情况下,我们会从名称中删除create,而我们最终不会(通常)使用return this;,因为如果该功能没有返回不同的名称对象,默认情况下new XYZ的结果是new运算符创建的对象,并作为this提供给函数:

&#13;
&#13;
function Person() {
  this.firstName = 'Lilly';
  this.lastName = 'Louis';

  Object.defineProperty(this, 'fullName', {
    get: function() {
      return this.firstName + ' ' + this.lastName;
    },
    set: function(name) {
      var words = name.split(' ');
      this.firstName = words[0] || '';
      this.lastName = words[1] || '';
    }
  });
}

var p1 = new Person();
console.log("Person's default name is \"" + p1.fullName + "\"");
&#13;
&#13;
&#13;

答案 1 :(得分:1)

这是因为你创建了一个person变量,但从未返回它。因此,函数没有返回任何内容,并且赋值未定义:

function createPerson() {
    var person = {
        firstName: 'Lilly',
        lastName: 'Louis',
    };

    Object.defineProperty(person, 'fullName', {
        get: function() { return this.firstName + ' ' + this.lastName; },
        set: function(name) {
            var words = name.split(' ');
            this.firstName = words[0] || '';
            this.lastName = words[1] || '';
        }
    });
    return person; // Add this line
}