JavaScript中的“ new”关键字是什么?

2020/09/15 16:31 · javascript ·  · 0评论

newJavaScript中的关键字可能会相当混乱首次遇到它的时候,人们往往会认为JavaScript是不是面向对象的编程语言。

  • 它是什么?
  • 它解决什么问题?
  • 什么时候合适,什么时候不合适?

它做五件事:

  1. 它创建一个新对象。这个对象的类型就是object
  2. 它将这个新对象的内部不可访问的[[prototype]](即__proto__)属性设置为构造函数的外部可访问原型对象(每个函数对象都会自动具有prototype属性)。
  3. 它使this变量指向新创建的对象。
  4. 每当this提及时,它将使用新创建的对象执行构造函数
  5. 除非构造函数返回非null对象引用,否则它将返回新创建的对象在这种情况下,将返回该对象引用。

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

new ConstructorFunction(arg1, arg2)

完成此操作后,如果请求新对象的未定义属性,则脚本将改为检查对象的[[prototype]]对象的属性。这就是您可以获得类似于JavaScript中传统类继承的方法的方法。

关于此点最困难的部分是点号2。每个对象(包括函数)都具有称为[[prototype]]的内部属性只能在对象创建时设置,可以使用newObject.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'

就像类继承一样,因为现在,您使用的所有对象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对象(AB)。window之所以将其添加到,是因为window这样执行时调用该函数的对象,而this在函数中是调用该函数的对象。至少在Javascript中。

现在,用这样的方式调用它new

var bar = new Foo();

当您添加new到函数调用中时,将会发生一个新对象(即var bar = new Object())的创建this并且函数内的指向Object刚创建的新对象,而不是指向调用该函数的对象。所以,bar现在与属性的对象AB任何函数都可以是构造函数,但这并不总是很有意义。

除了丹尼尔·霍华德(Daniel Howard)的答案,这是做什么的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是一种基于原型的语言。

已经有一些非常好的答案,但是我要发布一个新的答案,以强调我对以下情况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;在函数末尾强制插入一条语句。此处的窗口是this获取新对象AB属性的调用对象(上下文

情况二

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关键字创建了一个新对象,该对象充当所this指向的匿名函数的调用对象(上下文Foo在这种情况下AB成为新创建的对象的属性(代替窗口对象)。由于您没有任何显式的return语句,因此JavaScript解释程序会强制插入return语句以返回由于使用new关键字而创建的新对象

情况三

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关键字创建了一个新对象,该对象充当所this指向的匿名函数的调用对象(上下文Foo再次,AB成为新创建对象的属性。但是这次您有一个显式的return语句,因此JavaScript解释器将不会做任何事情。

在情况III中要注意的是,由于new关键字而创建的对象已从雷达中丢失。bar实际上指向一个完全不同的对象,该对象不是JavaScript解释程序由于new关键字而创建的对象

引用Java Scripit的David Flanagan:《权威指南》(第6版),第二章。4,第62页:

计算对象创建表达式时,JavaScript首先创建一个新的空对象,就像对象初始化程序{}创建的对象一样。接下来,它将使用指定的参数调用指定的函数,并将新对象作为this关键字的值传递。然后,函数可以使用它来初始化新创建的对象的属性。编写用作构造函数的函数不会返回值,并且对象创建表达式的值是新创建和初始化的对象。如果构造函数确实返回了一个对象值,则该值将成为对象创建表达式的值,并且新创建的对象将被丢弃。

- 其他信息 -

上述情况的代码段中使用的函数在JS world中具有特殊名称,如下所示:

情况一和二 -构造函数

情况三 -工厂功能。工厂函数不应new我用来解释当前线程中概念的关键字一起使用

您可以在线程中了解它们之间的区别

摘要:

new关键字以JavaScript用于创建从一个构造函数的对象。new关键字的构造函数调用之前放置,并会做以下几件事:

  1. 创建一个新对象
  2. 将此对象的原型设置为构造函数的prototype属性
  3. this关键字绑定到新创建的对象并执行构造函数
  4. 返回新创建的对象

例:

function Dog (age) {
  this.age = age;
}

const doggie = new Dog(12);

console.log(doggie);
console.log(Object.getPrototypeOf(doggie) === Dog.prototype) // true

到底发生了什么:

  1. const doggie 说:我们需要内存来声明变量。
  2. 分配运算符=说:我们将使用表达式后的表达式来初始化此变量=
  3. 表达式是new Dog(12)JS引擎看到new关键字,创建一个新对象并将原型设置为Dog.prototype
  4. 使用this设置为新对象执行构造函数在此步骤中,将年龄分配给新创建的小狗对象。
  5. 返回新创建的对象,并将其分配给变量doggie。

有时候代码比文字容易:

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关键字改变正在运行在其下的功能的上下文和指针返回到该上下文。

当您不使用new关键字时,函数在其下Vehicle()运行的上下文与您从中调用该Vehicle函数的上下文相同this关键字将指向同一个语境。使用时new Vehicle(),会创建一个新的上下文,因此this函数内的关键字引用了新的上下文。您得到的是新创建的上下文。

new关键字是创建新的对象实例。是的,javascript是一种动态编程语言,它支持面向对象的编程范例。关于对象命名的约定是,对于应该由new关键字实例化的对象,始终使用大写字母。

obj = new Element();
 " Every object (including functions) has this internal property called [[prototype]]" 

每个函数都有一个原型对象,该对象会自动设置为使用该函数创建的对象的原型。

你们可以轻松检查:

const a = { name: "something" };
console.log(a.prototype); // undefined because it is not directly accessible

const b = function () {
  console.log("somethign");};

console.log(b.prototype); // returns b {}

但是每个函数和对象都有__proto__指向该对象或函数原型的属性。 __proto__prototype2个不同的术语。我想我们可以这样评论:“每一个对象通过链接到一个原型

console.log(a.__proto__); // returns {}
console.log(b.__proto__); // returns [Function]

你们可以在终端上轻松检查。那么什么是构造函数。

function CreateObject(name,age){
    this.name=name;
    this.age =age
}

首先要注意的三件事:

1-我们没有使用return关键字。new会处理的。

2-函数名称大写,因此当开发人员看到您的代码时,他们可以理解他们必须使用new关键字。

3-我们不使用箭头功能。因为在this创建箭头功能(即“窗口”)的那一刻就拾取了参数的值箭头函数在词法上是作用域的,不是动态的。词汇在这里是指本地。箭头函数带有其本地“ this”值。

const me=new CreateObject("yilmaz","21")

new 调用该函数,然后创建一个空对象{},然后添加具有“ name”值的“ name”键和具有参数“ age”值的“ age”键。

当我们调用一个函数时,将使用“ this”和“ arguments”创建一个新的执行上下文,这就是“ new”可以访问这些参数的原因。

默认情况下,构造函数内部的此对象将指向“窗口”对象,但new会对其进行更改。“ this”指向创建的空对象{},然后将属性添加到新创建的对象。如果您定义了没有“ this”属性的任何变量,则不会将其添加到对象中。

function CreateObject(name,age){
    this.name=name;
    this.age =age;
    const myJob="developer"
}

myJob属性不会添加到该对象,因为没有任何引用指向新创建的对象。

   const me= {name:"yilmaz",age:21} // there is no myJob key

一开始我说每个函数都有“原型”属性,包括构造函数。我们可以将方法添加到构造函数的原型中,以便从该函数创建的每个对象都可以访问它。

 CreateObject.prototype.myActions=function(){ //define something}

现在“我”对象可以使用“ myActions”方法。

javascript具有内置的构造函数:Function,Boolean,Number,String ..

如果我创建

const a = new Number(5);
console.log(a);  // [Number: 5]
console.log(typeof a); // object

使用创建的任何new对象都有对象类型。现在“ a”可以访问Number.prototype中存储的所有方法如果我定义

const b = 5;
console.log(a === b);//false

a和b为5,但a为宾语,b为基本语。即使b是原始类型,在创建它时,javascript也会自动用Number()将其包装,因此b可以访问Number.prototype内部的所有方法。

当您要创建具有相同属性和方法的多个相似对象时,构造函数非常有用。这样,您就不会分配额外的内存,因此您的代码将更高效地运行。

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

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

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

实例继承自prototype构造函数的。因此,以上述示例为例...

foo.bar; // 'bar'

每个平台的JavaScript差异很大,因为它始终是原始规范EcmaScript的实现。

无论如何,独立于实现的所有遵循EcmaScript规范权利的所有JavaScript实现都将为您提供面向对象的语言。根据ES标准:

ECMAScript是一种面向对象的编程语言,用于在主机环境中执行计算和操纵计算对象。

因此,现在我们已经同意JavaScript是EcmaScript的实现,因此它是一种面向对象的语言。new在任何面向对象的语言中,操作的定义都说,该关键字用于从某种类型的类(包括匿名类型,如C#)中的类创建对象实例。

在EcmaScript中,我们不使用类,您可以从规范中读取:

ECMAScript不使用C ++,Smalltalk或Java中的类。相反,可以通过各种方式创建对象,包括通过文字符号或通过创建对象的构造函数,然后执行通过将初始值分配给它们的属性来初始化全部或部分对象的代码。每个构造函数都是一个函数,具有名为“ prototype”的属性,该属性用于实现基于原型的继承和共享属性。通过

在新表达式中使用构造函数
来创建对象例如,new Date(2009,11)创建一个新的Date对象。不使用new调用构造函数的后果取决于构造函数。例如,Date()生成当前日期和时间的字符串表示形式,而不是对象。

Javascript不是一种面向对象的编程语言,因此JavaScript工作中使用“ DELEGATION PROCESS”LOOK UP过程也称为原型委托或原型继承。

如果您尝试从一个对象,它并没有,JavaScript引擎外观为对象的原型(和它的原型,每次1步以上)获得属性的值它的原型链untll链端高达这是Object.prototype == null(标准对象原型)。此时,如果未定义属性或方法,则返回未定义

因此,使用new关键字可以手动完成一些任务,例如

  1. 手动创建对象,例如newObj。
  2. 在JS spec [[prototype]](即proto)中使用proto(又名dunder proto)进行隐藏债券创建
  3. 引用并将属性分配给 newObj
  4. newObj对象的返回

所有操作都是手动完成的。

function CreateObj(value1, value2) {
  const newObj = {};
  newObj.property1 = value1;
  newObj.property2 = value2;
  return newObj;
}
var obj = new CreateObj(10,20);

obj.__proto__ === Object.prototype;              // true
Object.getPrototypeOf(obj) === Object.prototype // true

Javascript关键字new有助于自动执行此过程:

  1. 创建新的对象文字,其标识为 this:{}
  2. 引用并将属性分配给 this
  3. 对Function.prototype共享空间的隐藏键创建[[prototype]](即proto
  4. this对象{}的隐式返回
function CreateObj(value1, value2) {
  this.property1 = value1;
  this.property2 = value2;
}

var obj = new CreateObj(10,20);
obj.__proto__ === CreateObj.prototype             // true
Object.getPrototypeOf(obj) == CreateObj.prototype // true

在没有新关键字的情况下调用构造函数:

=> this: Window

function CreateObj(value1, value2) {
  var isWindowObj = this === window;
  console.log("Is Pointing to Window Object", isWindowObj);
  this.property1 = value1;
  this.property2 = value2;
}
var obj = new CreateObj(10,20); // Is Pointing to Window Object false
var obj = CreateObj(10,20); // Is Pointing to Window Object true
window.property1; // 10
window.property2; // 20
本文地址:http://javascript.askforanswer.com/javascriptzhongde-newguanjianzishishenme.html
文章标签: ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!