该 new
JavaScript中的关键字在第一次遇到时会非常混乱,因为人们倾向于认为JavaScript不是面向对象的编程语言。
- 它是什么?
- 它解决了什么问题?
- 什么时候适当,什么时候不适合?
该 new
JavaScript中的关键字在第一次遇到时会非常混乱,因为人们倾向于认为JavaScript不是面向对象的编程语言。
它做了5件事:
this
变量指向新创建的对象。this
提到了。null
对象参考。在这种情况下,将返回该对象引用。注意: 构造函数 是指之后的功能 new
关键字,如
new ConstructorFunction(arg1, arg2)
完成此操作后,如果请求新对象的未定义属性,脚本将检查对象的属性 [[原型]] 相反的财产对象。这就是你如何在JavaScript中获得类似于传统类继承的东西。
关于这一点最困难的部分是第2点。每个对象(包括函数)都有这个内部属性 [[原型]]。它可以 只要 在对象创建时设置,或者 新,与 的Object.create,或基于文字(函数默认为Function.prototype,数字为Number.prototype等)。它只能用 Object.getPrototypeOf(someObject)。有 没有 设置或读取此值的其他方法。
功能,除了隐藏 [[原型]] 财产,也有一个叫做的财产 原型,您可以访问和修改,为您创建的对象提供继承的属性和方法。
这是一个例子:
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'
它类似于类继承,因为现在,您使用的任何对象 new 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 Foo = function(){
this.A = 1;
this.B = 2;
};
如果你将其称为独立函数,如下所示:
Foo();
执行此函数将添加两个属性 window
对象(A
和 B
)。它将它添加到 window
因为 window
是这样执行它时调用函数的对象,和 this
在函数中是调用函数的对象。至少在Javascript中。
现在,这样称呼它 new
:
var bar = new Foo();
添加时会发生什么 new
函数调用是创建一个新对象(只是 var bar = new Object()
)那个 this
在功能内指向新的 Object
你刚刚创建的,而不是调用函数的对象。所以 bar
现在是具有属性的对象 A
和 B
。任何函数都可以是构造函数,它并不总是有意义的。
除了丹尼尔霍华德的回答,这是什么 new
做(或至少似乎做):
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;
}
而
var obj = New(A, 1, 2);
相当于
var obj = new A(1, 2);
在浏览器控制台中尝试以下代码。
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的答案:)
所以它可能不适合创作 对象的实例
它完全用于此。你定义一个函数构造函数,如下所示:
function Person(name) {
this.name = name;
}
var john = new Person('John');
然而,ECMAScript的额外好处是你可以扩展 .prototype
财产,所以我们可以做...
Person.prototype.getName = function() { return this.name; }
从这个构造函数创建的所有对象现在都有一个 getName
因为他们可以访问的原型链。
JavaScript的 是 面向对象的编程语言,它完全用于创建实例。它是基于原型的,而不是基于类的,但这并不意味着它不是面向对象的。
Javascript是一种动态编程语言,支持面向对象的编程范例,它用于创建对象的新实例。
对象不需要类 - Javascript是一个 基于原型 语言。
有时代码比单词更容易:
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的风格,因为它让我在函数内外有了更多的灵活性。
该 new
keyword用于创建新对象实例。是的,javascript是一种动态编程语言,它支持面向对象的编程范例。关于对象命名的约定是,对于应该由new关键字实例化的对象,总是使用大写字母。
obj = new Element();
已经有一些非常好的答案,但我发布了一个新的答案,以强调我对案例的观察 III 下面讲一下当你在一个函数中有一个显式的return语句时会发生什么 new
升起看看下面的案例:
案例一:
var Foo = function(){
this.A = 1;
this.B = 2;
};
console.log(Foo()); //prints undefined
console.log(window.A); //prints 1
以上是调用指向的匿名函数的简单情况 Foo
。当你调用这个函数时它会返回 undefined
。由于没有明确的return语句所以JavaScript解释器强制插入一个 return undefined;
声明在函数的最后。这里窗口是调用对象(contextual this
)获得新的 A
和 B
属性。
案例二:
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
在这里JavaScript解释器看到了 new
keyword创建一个新对象,它充当调用对象(contextual this
)由匿名函数指出 Foo
。在这种情况下 A
和 B
成为新创建的对象的属性(代替窗口对象)。由于您没有任何显式的return语句,因此JavaScript解释器强制插入return语句以返回由于使用而创建的新对象 new
关键词。
案例III:
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.
这里再次看到JavaScript解释器 new
keyword创建一个新对象,它充当调用对象(contextual this
)由匿名函数指出 Foo
。再次, A
和 B
成为新创建的对象的属性。但这次你有一个明确的return语句,所以JavaScript解释器会 不 做任何自己的事情。
要注意的事情 III 是由于创建的对象 new
关键字从你的雷达中丢失了。 bar
实际上是指向一个完全不同的对象,这个对象不是JavaScript解释器创建的对象 new
关键词。
每个JavaScript的JavaScript可能因平台而异,因为它始终是原始规范EcmaScript的实现。
在任何情况下,独立于实现的所有遵循EcmaScript规范的JavaScript实现都将为您提供面向对象的语言。根据ES标准:
ECMAScript是一种面向对象的编程语言 执行计算和操纵计算对象 在主机环境中。
所以现在我们已经同意JavaScript是EcmaScript的一个实现,因此它是面向对象的语言。的定义 new
任何面向对象语言的操作都表示,这种关键字用于从某种类型的类创建对象实例(包括匿名类型,如C#)。
在EcmaScript中,我们不使用类,因为您可以从规范中读取:
ECMAScript不使用诸如C ++,Smalltalk或Java中的类。相反,可以以各种方式创建对象,包括via 一个文字符号或通过构造函数创建对象然后执行代码,通过分配初始化来初始化它们的全部或部分 值的属性。每个构造函数都是一个函数 财产命名 - 原型‖用于实现基于原型的继承和共享属性。对象是由。创建的
在新表达式中使用构造函数;例如,新的 Date(2009,11)创建一个新的Date对象。调用构造函数 不使用new会产生依赖于构造函数的后果。 例如,Date()生成一个字符串表示 当前日期和时间而不是对象。