What is the 'new' keyword in JavaScript?
javascript中的
- 这是怎么一回事?
- 它能解决什么问题?
- 什么时候合适,什么时候不合适?
它可以做5件事:
注:constructor函数是指
1 | new ConstructorFunction(arg1, arg2) |
完成后,如果请求新对象的未定义属性,脚本将检查对象的[[原型]]对象的属性。这就是如何在JavaScript中获得类似于传统类继承的东西。
最困难的部分是第2点。每个对象(包括函数)都有一个称为[[原型]]的内部属性。它只能在对象创建时设置,可以使用new、object.create或基于文本(函数默认为function.prototype、numbers to number.prototype等)。它只能用object.getPrototypeof(someObject)读取。没有其他方法可以设置或读取此值。
函数除了隐藏的[[原型]]属性外,还有一个名为原型的属性,您可以通过它访问和修改,为所生成的对象提供继承的属性和方法。
下面是一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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' |
这类似于类继承,因为现在,使用
如果您想要子类之类的东西,那么您可以这样做:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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 |
在找到这一页之前,我读了很多关于这一主题的垃圾,在那里用漂亮的图表很好地解释了这一点。
假设您具有以下功能:
1 2 3 4 | var Foo = function(){ this.A = 1; this.B = 2; }; |
如果您将其称为这样的独立函数:
1 | Foo(); |
执行此函数将向
现在,用
1 | var bar = new Foo(); |
当您向函数调用中添加
除了Daniel Howard的回答之外,以下是
1 2 3 4 5 6 7 8 9 10 11 | function New(func) { var res = {}; if (func.prototype !== null) { res.__proto__ = func.prototype; } var ret = func.apply(res, Array.prototype.slice.call(arguments, 1)); if ((typeof ret ==="object" || typeof ret ==="function") && ret !== null) { return ret; } return res; } |
同时
1 | var obj = New(A, 1, 2); |
等于
1 | var obj = new A(1, 2); |
让初学者更好地理解它
在浏览器控制台中尝试以下代码。
1 2 3 4 5 6 7 8 9 10 11 12 | function Foo() { return this; } var a = Foo(); //returns window object var b = new Foo(); //returns empty object of foo a instanceof Window; // true a instanceof Foo; // false b instanceof Window; // false b instanceof Foo; // true |
现在您可以阅读社区wiki答案:)
so it's probably not for creating
instances of object
正是为了这个。您可以这样定义函数构造函数:
1 2 3 4 5 | function Person(name) { this.name = name; } var john = new Person('John'); |
然而,ecmascript的额外好处是,您可以使用
1 | Person.prototype.getName = function() { return this.name; } |
从这个构造函数创建的所有对象现在都将有一个
JavaScript是一种面向对象的编程语言,它完全用于创建实例。它是基于原型的,而不是基于类的,但这并不意味着它不是面向对象的。
JavaScript是一种支持面向对象编程范式的动态编程语言,用于创建新的对象实例。
对象不需要类-JavaScript是一种基于原型的语言。
已经有一些非常好的答案了,但是我发布了一个新的答案来强调我对下面的案例三的观察,即当你在一个函数中有一个明确的返回语句时会发生什么,而这个函数是你正在执行的。请看以下案例:
案例一:
1 2 3 4 5 6 | var Foo = function(){ this.A = 1; this.B = 2; }; console.log(Foo()); //prints undefined console.log(window.A); //prints 1 |
上面是调用
案例二:
1 2 3 4 5 6 7 | var Foo = function(){ this.A = 1; this.B = 2; }; var bar = new Foo(); console.log(bar()); //illegal isn't pointing to a function but an object console.log(bar.A); //prints 1 |
在这里,看到
III案:
1 2 3 4 5 6 7 8 | var Foo = function(){ this.A = 1; this.B = 2; return {C:20,D:30}; }; var bar = new Foo(); console.log(bar.C);//prints 20 console.log(bar.A); //prints undefined. bar is not pointing to the object which got created due to new keyword. |
在这里,看到
在第三种情况下需要注意的是,由于
有时代码比文字容易:
1 2 3 4 5 6 7 8 9 | 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样式,因为它在函数内部和外部都提供了更多的灵活性。
1 | obj = new Element(); |
如果不使用
好吧,每个SI的javascript在不同平台之间可能有很大的不同,因为它始终是原始规范ecmascript的实现。
在任何情况下,与实现无关,所有遵循ECMAScript规范的JavaScript实现都将为您提供一种面向对象的语言。根据ES标准:
ECMAScript is an object-oriented programming language for
performing computations and manipulating computational objects
within a host environment.
现在我们已经同意了JavaScript是ECMAScript的一个实现,因此它是一种面向对象的语言。在任何面向对象的语言中,
在ecmascript中,我们不使用类,正如您可以从规范中看到的那样:
ECMAScript does not use classes such as those in C++, Smalltalk, or Java. Instead objects may be created in various ways including via
a literal notation or via constructors which create objects and then execute code that initializes all or part of them by assigning initial
values to their properties. Each constructor is a function that has a
property named ―
prototype ‖ that is used to implement prototype - based inheritance and shared properties. Objects are created by
using constructors in new expressions; for example, new
Date(2009,11) creates a new Date object. Invoking a constructor
without using new has consequences that depend on the constructor.
For example, Date() produces a string representation of the
current date and time rather than an object.
总结:
在javascript中使用
例子:
1 2 3 4 5 6 7 8 | function Dog (age) { this.age = age; } const doggie = new Dog(12); console.log(doggie); console.log(doggie.__proto__ === Dog.prototype) // true |
具体发生了什么:
1 2 3 4 5 | var Foo = function() {}; Foo.prototype.bar = 'bar'; var foo = new Foo(); foo instanceof Foo; // true |
实例继承自构造函数函数的
1 | foo.bar; // 'bar' |