JavaScript中的新关键字在第一次遇到时可能会非常令人困惑,因为人们倾向于认为JavaScript不是一种面向对象的编程语言。

这是怎么一回事?它解决了什么问题?什么时候合适,什么时候不合适?


当前回答

new关键字更改运行函数的上下文,并返回指向该上下文的指针。

如果不使用new关键字,则运行函数Vehicle()的上下文与调用Vehicle函数的上下文相同。this关键字将引用相同的上下文。当您使用new Vehicle()时,将创建一个新上下文,因此函数中的关键字this将引用新上下文。您得到的回报是新创建的上下文。

其他回答

new关键字使用函数作为构造函数创建对象的实例。例如:

var Foo = function() {};
Foo.prototype.bar = 'bar';

var foo = new Foo();
foo instanceof Foo; // true

实例继承自构造函数的原型。因此,在上面的例子中。。。

foo.bar; // 'bar'

JavaScript是一种支持面向对象编程范式的动态编程语言,用于创建对象的新实例。

对象不需要类。JavaScript是一种基于原型的语言。

它做5件事:

它将创建一个新对象。此对象的类型只是对象。它将此新对象的内部、不可访问的[[prototype]](即__proto__)属性设置为构造函数的外部、可访问的原型对象(每个函数对象都自动具有原型属性)。它使该变量指向新创建的对象。每当提到这一点时,它都会使用新创建的对象来执行构造函数。它返回新创建的对象,除非构造函数返回非空对象引用。在这种情况下,将返回该对象引用。

注意:构造函数是指new关键字之后的函数,如

new ConstructorFunction(arg1, arg2)

完成此操作后,如果请求了新对象的未定义属性,脚本将检查对象的[[prototype]]对象的属性。这就是如何在JavaScript中获得类似于传统类继承的东西。

这方面最困难的部分是第2点。每个对象(包括函数)都有一个名为[[prototype]]的内部属性。只能在对象创建时使用new、object.create或基于文本(函数默认为Function.prototype,数字默认为Number.prototype等)设置它。只能使用object.getPrototypeOf(someObject)读取它。没有其他方法设置或读取此值。

除了隐藏的[[prototype]]属性外,函数还有一个名为prototype的属性,您可以通过它访问和修改,为所创建的对象提供继承的财产和方法。


下面是一个示例:

ObjMaker = function() {this.a = 'first';};
// ObjMaker is just a function, there's nothing special about it that makes 
// it a constructor.

ObjMaker.prototype.b = 'second';
// like all functions, ObjMaker has an accessible prototype property that 
// we can alter. I just added a property called 'b' to it. Like 
// all objects, ObjMaker also has an inaccessible [[prototype]] property
// that we can't do anything with

obj1 = new ObjMaker();
// 3 things just happened.
// A new, empty object was created called obj1.  At first obj1 was the same
// as {}. The [[prototype]] property of obj1 was then set to the current
// object value of the ObjMaker.prototype (if ObjMaker.prototype is later
// assigned a new object value, obj1's [[prototype]] will not change, but you
// can alter the properties of ObjMaker.prototype to add to both the
// prototype and [[prototype]]). The ObjMaker function was executed, with
// obj1 in place of this... so obj1.a was set to 'first'.

obj1.a;
// returns 'first'
obj1.b;
// obj1 doesn't have a property called 'b', so JavaScript checks 
// its [[prototype]]. Its [[prototype]] is the same as ObjMaker.prototype
// ObjMaker.prototype has a property called 'b' with value 'second'
// returns 'second'

这类似于类继承,因为现在,使用新的ObjMaker()创建的任何对象都似乎继承了“b”属性。

如果你想要一个类似子类的东西,那么你可以这样做:

SubObjMaker = function () {};
SubObjMaker.prototype = new ObjMaker(); // note: this pattern is deprecated!
// Because we used 'new', the [[prototype]] property of SubObjMaker.prototype
// is now set to the object value of ObjMaker.prototype.
// The modern way to do this is with Object.create(), which was added in ECMAScript 5:
// SubObjMaker.prototype = Object.create(ObjMaker.prototype);

SubObjMaker.prototype.c = 'third';  
obj2 = new SubObjMaker();
// [[prototype]] property of obj2 is now set to SubObjMaker.prototype
// Remember that the [[prototype]] property of SubObjMaker.prototype
// is ObjMaker.prototype. So now obj2 has a prototype chain!
// obj2 ---> SubObjMaker.prototype ---> ObjMaker.prototype

obj2.c;
// returns 'third', from SubObjMaker.prototype

obj2.b;
// returns 'second', from ObjMaker.prototype

obj2.a;
// returns 'first', from SubObjMaker.prototype, because SubObjMaker.prototype 
// was created with the ObjMaker function, which assigned a for us

在最后找到这一页之前,我读了大量关于这一主题的垃圾,在那里用漂亮的图表很好地解释了这一点。

有时代码比文字更容易:

var func1 = function (x) { this.x = x; }                   // Used with 'new' only
var func2 = function (x) { var z={}; z.x = x; return z; }  // Used both ways
func1.prototype.y = 11;
func2.prototype.y = 12;

A1 = new func1(1);  // Has A1.x  AND  A1.y
A2 =     func1(1);  // Undefined ('this' refers to 'window')
B1 = new func2(2);  // Has B1.x  ONLY
B2 =     func2(2);  // Has B2.x  ONLY

对我来说,只要我不做原型,我就使用func2的样式,因为它给了我函数内外更多的灵活性。

JavaScript是一种面向对象的编程语言,它完全用于创建实例。它是基于原型的,而不是基于类的,但这并不意味着它不是面向对象的。