美文网首页
Javascript 中的构造函数

Javascript 中的构造函数

作者: 简单的怪石头 | 来源:发表于2020-03-26 21:06 被阅读0次

在静态语言中,一般一个类都有自己的构造函数。对于Javascript而言,它其实也有自己的‘构造函数’,但是其‘构造函数’和静态语言相比存在很大的差别。
直观来讲构造函数其实就是在构建一个实例的时候调用的函数,那在Javascript中是不是这样呢?

普通对象中的构造函数

为了证明是否会如此,我们先看一下Javascript的构造函数都在哪儿。其实它的构造函数都在其所对应的原型上,只是我们有不同的方式去拿到他。对于普通的对象来讲,如下可以查看其构造函数:

const objectA = { name: "A's name" };
objectA.constructor   // ƒ Object() { [native code] }
objectA.__proto__.constructor // ƒ Object() { [native code] }

由以上例子可见,一个通过对象字面量构建的对象,其构造函数是指向原型链上层Object的。以下测试代码可以帮助更清晰的了解实例对象&Object之间构造函数的关系

objectA.constructor === objectA.__proto__.constructor // true
objectA.constructor === Object //  true
objectA.consturctor === Object.prototype.constructor // true

第一行很好理解,但是第二行和第三行是怎么回事?而且可能你会问Object.constructor又和objectA.constructor是什么关系?

函数的构造函数

其实Object在Javascript中本质上是一个函数,一个直观的证明就是

Object instanceof Function   // true

函数本身来讲也有自己的构造函数,且在声明函数之后,其原型上构造函数就默认指向了自身。

function funA() { console.log("this's function A");  }

funA.prototype.constructor === funA  // true

通过new关键字来用函数构建一个实例,它的构造函数就是指向函数原型上的构造函数的

const instanceA = new funA();
instanceA.constructor === funA   // true
instanceA.constructor === funA.prototype.constructor  // true

这样一来其实就可以和之前的普通对象的构造函数表现一致了。区别仅仅是在实例化的时候一个使用了对象字面量,一个使用了new关键字。但是本质上来讲对象字面量实例化对象和new Object({a: "name"})没有区别,所以这就能解释为什么objectA.constructor === Object结果为true了

类中的构造函数

在es6提供了关键字class,可以使得我们能像静态语言一样去声明一个类,但实质上它不过是一个语法糖,内部还是由函数、原型来实现的。所以就构造函数而言它的表现其实和函数的构造是一致的。

class ClassA {
  constructor() { console.log("this is classA constructor"); }
}
ClassA.prototype.constructor === ClassA // true
const instanceA = new ClassA();

instanceA.constructor === ClassA   // true
instanceA.constructor === ClassA.prototype.constructor  // true

是真的构造函数吗

在静态语言中,我们需要构建一个类的实例,需要使用new关键字去实例化一个对象,在使用new关键时会调用声明在类中的构造函数,那么在Javascript中是不是这样呢。我们可以拿类来做实验,这可能比较直观

class ClassA {
  constructor() { console.log("this is classA constructor"); }
}
ClassA.prototype.constructor === ClassA // true
const instanceA = new ClassA();  // this is classA constructor

可以看到当我们去使用new关键直的时候,确实调用了在类中声明的构造函数中的代码。但是可能还不能这样直接断定Javascript确实是调用构造函数来构建的,看下面有趣的例子:

class ClassA {
  constructor() {
   console.log("this is classA constructor");
 }
}
ClassA.prototype.constructor === ClassA // true
const instanceA = new ClassA();  // this is classA constructor

ClassA.prototype.constructor = function() { 
  console.log("this is new constructor")
}
const instanceB = new ClassA();  // this is classA constructor

首先需要说明的是,在原型上的constructor是可写的,所以我们是可以重写原型上的constructor的,如上代码所示。如果和静态语言一样,在构建实例的时候,那么就应该使用新声明的构造函数啊,但是并没有这样。这使得Javascript中的class让人难以理解,对于习惯面向对象编程的同学来说更是头疼。就光能直接重写构造函数就已经不可理喻了。但是这个其实并不是什么大问题,因为类其实在Javascript中本来就只是一个语法糖,让习惯类写法的人更加舒畅,但是其背后的本质还是在使用原型机制,所以要将静态语言中类的一套说法硬搬到Javascript是不可能说得明白的。
那既然如此constructor在Javascript中有什么用处呢?
之前看到一些比较神奇的用法是,通过它来判断一个对象是不是某个函数的实例

instanceA.__proto__.constructor === funcA.prototype.constructor

这种比较是极不可靠的,因为我们在上一个示例已经看到,你可以随意的更改一个函数或类的构造函数,但是更改之后的实例化对象仍然应该是这个函数或者类的实例,一个例子一目了然

class ClassA {
  constructor() {
   console.log("this is classA constructor");
 }
}
const instanceA = new ClassA();  
ClassA.prototype.constructor = function() { 
  console.log("this is new constructor")
}
const instanceB = new ClassA();  
instanceA.__proto__.constructor === instanceB.__proto__.constructor   // false
instanceA instanceof ClassA   // true
instanceB instanceof ClassA   // true

constructor的随意告诉你,它是不可靠的,所以一般我们在编程中基本上不会依赖构造函数,即使类中有使用关键字,但是其本质上是在声明函数体中的内容,并不是在声明一个你以为的‘构造函数’。原型上的constructor方法,不过是在声明方法的时候顺手加上去的,仅此而已。

小结

Javascript中的构造函数和静态类型中的构造函数是完全不同的,而且Javascript原型上的构造函数其实并没有那么可靠,它在函数声明的时候指向了函数本身,但是在函数声明之后却仍然可以被修改,这个修改并不会修改函数原来的声明。它在Javascript中是随意的也是不可靠的,所以编程中也不会特意去使用或者修改它。就让它静静的呆着就好。
ES6 提供了类的写法,但是并不能将类的一切东西生搬硬套到Javascript中,理解并接纳其本身不同于其他语言的特色才是较为重要的。

相关文章

  • 构造函数和原型对象

    javascript使用构造函数和原型对象来进行面向对象编程 构造函数 在 JavaScript 中,构造器其实就...

  • JavaScript 面向对象编程

    构造函数 JavaScript中的构造函数是创建对象时调用的函数,写法如下: 定义Person构造函数(默认构造函...

  • javaScript面向对象—构造函数,原型和原型链

    构造函数 什么是构造函数 在javaScript中,用new关键字来调用的函数,称为构造函数。一般将构造函数的首字...

  • 前端高频面试题之——原型链

    JavaScript中的构造函数 原型是什么 面向对象语言中,类派生实例,JavaScript的函数可以作为构造器...

  • JS对象继承相关

    propertype 在JavaScript中通过构造函数来构造对象每个函数有他的propertype指向该构造函...

  • js构造函数的定义

    1.什么是构造函数 在 JavaScript 中,用 new 关键字来调用的函数,称为构造函数。构造函数首字母一般...

  • 原型与原型链

    构造函数与原型 JavaScript 语言使用构造函数(constructor)作为对象的模板。所谓”构造函数”,...

  • Javascript 中的构造函数

    在静态语言中,一般一个类都有自己的构造函数。对于Javascript而言,它其实也有自己的‘构造函数’,但是其‘构...

  • JavaScript构造函数

    在JavaScript编程中,构造函数是面向对象编程的基础。创建构造函数和普通函数一样,也是使用function关...

  • Javascript构造函数(一)概念,注意事项,defineP

    构造函数 1.概念 在JavaScript中,任何合法的函数都可以作为对象的构造函数,既包含系统内置函数,也包括用...

网友评论

      本文标题:Javascript 中的构造函数

      本文链接:https://www.haomeiwen.com/subject/ruonyhtx.html