Javascript - 如何创建新的函数实例

时间:2015-03-02 05:11:05

标签: javascript javascript-objects

我知道,我们可以通过以下方法创建新的函数实例。但我的问题是还有其他方法可以实现同样的目标吗?

var Person = function (firstName) {
  this.firstName = firstName;
  console.log('Person instantiated');
};

var person1 = new Person('Alice');
var person2 = new Person('Bob');

// Show the firstName properties of the objects
console.log('person1 is ' + person1.firstName); // logs "person1 is Alice"
console.log('person2 is ' + person2.firstName); // logs "person2 is Bob"

因为,new声明的某些时候失败了,我也没有得到error ..

特别是,在javascript oops概念中需要采用不同的方法。

有时候,我甚至在没有调用new关键词的情况下感到困惑,一切正常。使用new关键字与不使用关键字有什么不同?

示例:

var setColor = function (color) {
   return color;
}

var x = setColor('red');
var y = setColor('blue');

console.log(y);
console.log(x);

4 个答案:

答案 0 :(得分:2)

在调用函数时使用new关键字将函数内的上下文(this)设置为新实例化的对象,而不是window或其他一些上下文,为什么你可以在函数内部分配this.firstName,然后将其称为person1.firstName。

如果不使用new关键字,则this WONT的值为空白对象,因此您将分配给window。在这种情况下,您希望使用new,因为您将该函数用作构造函数。如果您不打算将该函数用作构造函数,则不希望使用new调用它。

答案 1 :(得分:1)

new [Function]关键字做了很多事情,但主要做的是:

  • 创建新对象
  • 使用[Function]的原型作为新对象的父原型
  • 使用this作为对新对象的引用,执行[Function]的内容

如果你在没有new的情况下调用这样的函数,this引用将按照通常为函数确定的方式确定,通常这将是全局对象。

你可以做的更容易就是使用严格的模式:

"use strict";

var Person = function (firstName) {
  this.firstName = firstName;
  console.log('Person instantiated');
};

var person1 = Person('Alice');

如果执行了上述代码,this将是null而不是全局对象,您将立即收到错误,而不是将属性分配给全局对象(并且很难 - 捕捉错误)。

使用new完全避免这些错误的一种方法是简单地让函数返回一个新对象而不是构造函数:

var person = function (firstName) {
  console.log('person instantiated');
  return {
      firstName: firstName
  };
};

var person1 = person('Alice');
var person2 = person('Bob');

如果您这样做,无论您是否使用new都无关紧要,因为该功能不使用this

编辑以下是关于原型的问题。如果您不熟悉原型,这是一个允许您指定将在对象的所有实例之间共享的属性和方法的功能:

"use strict";

var Person = function (firstName) {
  this.firstName = firstName;
  console.log('Person instantiated');
};

Person.prototype.getMyName = function () {
    return this.firstName;
};

var person1 = new Person('Alice');
console.log(person1.getMyName());

如果您这样做,那么使用new Person()创建的所有实例都将共享getMyName方法。

我稍后详述的new - 更少选项提供此自动原型扩展,但还有其他选择:

选项1 - 不要使用原型:

var person = function (firstName) {
  console.log('person instantiated');
  return {
      firstName: firstName,
      getMyName: function () {
          return this.firstName;
      }
  };
};

选项2 - 使用Object.create()扩展原型:

var person = function (firstName) {
  console.log('person instantiated');
  var person = Object.create(person.prototype);
  person.firstName = firstName;

  return person;
};

选项3 - 使用.extend()方法将原型的内容复制到新对象:

var person = function (firstName) {
  console.log('person instantiated');

  return _.extend({
      firstName: firstName
  }, person.prototype);
};

.extend()没有构建到JavaScript中,但是jQuery和lodash等几个库提供了与它基本相同的实现。

答案 2 :(得分:1)

我认为您需要更好地了解对象和原型设计在Javascript中的工作原理。

考虑您有一个用例,您想要一个代表user的对象,并存储他们的first_name

不使用任何功能,您只需创建一个具有所需属性的对象:

var person = {
    first_name: 'joel'
};

这是一个标准的javascript对象 - 没什么特别的,也没有使用new关键字来构造它。完成同样事情的另一种语法是:

var person = new Object();
person.first_name = 'joel';

再次 - 这只是一个标准对象 - 没什么特别的。

创建函数的new个实例的主要原因是使用javascript的原型系统。这类似于其他语言的类。我们假设您希望所有人的实例都有一个名为getName()的方法。您可以确保为每个人创建该方法......

var person = {
    first_name: 'joel',
    getName: function() {
        return this.first_name;
    }
};

...或

var person = new Object();
person.first_name = 'joel';
person.getName = function() {
    return this.first_name;
};

然而,对于这种事情,一种更好的方法,即你总是希望为每个用户定义这个方法,就是创建一个person对象的新实例,并定义{{ 1}}关于Person函数的prototype属性的方法:

getName

...或者根据您的示例,您可以使用function Person() {} Person.prototype.getName = function() { return this.first_name; } var user = new Person(); user.first_name = 'joel'; console.log(user.getName()); 构造函数的参数来设置第一个名称属性:

Person

请注意,在创建function Person(first_name) { this.first_name = first_name; } Person.prototype.getName = function() { return this.first_name; }; var user = new Person('joel'); console.log(user.getName()); 实例时,使用此方法始终会使用new关键字。当您考虑以下内容时,原因就变得清晰了:

Person

请注意,在上面的第4行中,您可以看到,在函数调用中省略了function Person() {this.first_name = 'joel'; return 'test';} console.log(window.first_name); // Undefined, as expected console.log(Person()); // Shows "test"; console.log(window.first_name); // shows "joel". console.log(new Person()); // Shows "{first_name: 'joel'}" 关键字,希望您使用它,您意外地修改了{{1}上的属性} object,而不是在新的常规对象上设置它。

有效 - 您可以考虑使用new关键字来使Person函数的返回值被忽略,而是您将返回一个Person对象的新实例。

另请注意,通过检查window是否等于{{1},可以通过省略函数内部new关键字来降低意外修改window对象的风险而是返回函数的新实例:

new

通过上述方法,您可以使用以下任一方法实例化this对象,两者都具有相同的效果:

window

有关javascript函数和原型对象如何工作的更多信息,我建议阅读http://www.w3schools.com/js/js_object_prototypes.asp

答案 3 :(得分:1)

使用闭包而不是对象的另一种可能的结构

此结构也可以嵌套创建私有静态变量

它没有使用这个词

var thing = function(private_var){

   function get(){
     console.log(private_var)
   }

   function set(z){
      private_var = z
   }

   return {
    get:get,
    set:set
   }


}

var x = thing(0)
var y = thing(1)

请注意:
这使某些类型的程序员感到恐慌和恐慌

&安培;&安培;重要的是x.say!== y.say