在其他语言中,new操作符都是用来实例化创建一个对象的,JavaScript 中同样如此,但是它又有一些不同。为了说清楚这个问题我们先来看一下JavaScript 中的类、原型、原型链、继承这些概念吧。

JavaScript 中没有传统类的概念,它的类就是一个方法,也就是说JavaScript 中是通过function来定义类的。比如我们可以这样子来定义一个类。
function Person(name, age) {
this.name = name;
this.age = age;
this.sing = function() { alert(this.name) }
}
那么,有类了就一定存在着继承,而js的继承跟传统的类继承模型不同,它是使用 prototype 原型模型。这经常被当作是 JavaScript 的缺点被提及,其实基于原型的继承模型比传统的类继承还要强大。 实现传统的类继承模型是很简单,但是实现 js中的原型继承则要困难的多。JavaScript 使用原型链的继承方式。我们来看下这个例子。
function Foo() {
this.value = 42;
}
Foo.prototype = {
method: function() {}
}; function Bar() {} // 设置Bar的prototype属性为Foo的实例对象
Bar.prototype = new Foo();
Bar.prototype.foo = 'Hello World'; // 修正Bar.prototype.constructor为Bar本身
Bar.prototype.constructor = Bar; var bar= new Bar() // 创建Bar的一个新实例 // 原型链
test [Bar的实例]
Bar.prototype [Foo的实例]
{ foo: 'Hello World' }
Foo.prototype
{method: ...};
Object.prototype
{toString: ... /* etc. */};

  上面的例子中,test 对象从 Bar.prototype 和 Foo.prototype 继承下来;因此, 它能访问 Foo 的原型方法 method。同时,它也能够访问那个定义在原型上的 Foo 实例属性 value。 需要注意的是 new Bar() 不会创造出一个新的 Foo 实例,而是 重复使用它原型上的那个实例;因此,所有的 Bar 实例都会共享相同的 value 属性。

  这里我觉得有必要来说一下原型、原型链和实例之间的关系。JavaScript中,每个函数都有一个prototype属性,这是一个指针,指向了这个函数的原型对象。这个对象包含这个函数创建的实例的共享属性和方法。也就是说原型对象中的属性和方法是所有实例共享。而这个原型对象有一个constructor属性,指向了该构造函数。每个通过该构造函数创建的对象都包含一个指向原型对象的内部指针__proto__。 原型链作为实现继承的主要方法,其基本思想是:让原型对象等于另一个类型的实例,这样原型对象将包含一个指向另一个原型的指针,相应的,另一个原型中也包含着一个指向另一个构造函数的指针,假如另一个原型又是另一个类型的实例,如此层层递进,就构成了实例与原型的链条,这个链条就称之为原型链.
         回到主题上,但我们使用new Foo()创造出一个示例这过程中它做了写什么事呢?
     1、创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型。
     2、属性和方法被加入到 this 引用的对象中。
     3、新创建的对象由 this 所引用,并且最后隐式的返回 this 。
var foo  = {};
foo.__proto__ = Object.prototype;
Object.call(foo);

  同理,当我们new Bar()的时候,也是创建了一个空对象,并且 this 变量引用该对象,同时,Bar.prototype = new Foo();然后bar.__proto__ = Foo.prototype,最后,由Foo.call(bar)隐式的返回了this; 其中,Bar.prototype = new Foo()会使得Bar.prototype.constructor == Foo,所以这里我们要使用Bar.prototype.constructor = Bar;把Bar自身的构造函数修正过来。

  到这里我们可以发现,JavaScript中的new操作与其说是新建了一个示例,更不如说做是由一个工厂模式产生出来一个实例。
我们再来看个例子,这个是汤姆大叔博客中的例子。
function A() {}
A.prototype.x = 10; var a = new A();
alert(a.x); // 10 – 从原型上得到 // 设置.prototype属性为新对象
// 为什么显式声明.constructor属性将在下面说明
A.prototype = {
constructor: A,
y: 100
}; var b = new A();
// 对象"b"有了新属性
alert(b.x); // undefined
alert(b.y); // 100 – 从原型上得到 // 但a对象的原型依然可以得到原来的结果
alert(a.x); // 10 - 从原型上得到 function B() {
this.x = 10;
return new Array();
} // 如果"B"构造函数没有返回(或返回this)
// 那么this对象就可以使用,但是下面的情况返回的是array
var b = new B();
alert(b.x); // undefined
alert(Object.prototype.toString.call(b)); // [object Array]

这里有两个主要特点:

  1. 首先,新创建对象的原型是从当前时刻函数的prototype属性获取的(这意味着同一个构造函数创建的两个创建对象的原型可以不同是因为函数的prototype属性也可以不同)。
  2. 其次,正如我们上面提到的,如果在对象初始化的时候,[[Call]]返回的是对象,这恰恰是用于整个new操作符的结果
 
文中例子来源于:http://bonsaiden.github.io/JavaScript-Garden/zh/

说说JavaScript 中的new吧的更多相关文章

  1. javascript中的Array对象 —— 数组的合并、转换、迭代、排序、堆栈

    Array 是javascript中经常用到的数据类型.javascript 的数组其他语言中数组的最大的区别是其每个数组项都可以保存任何类型的数据.本文主要讨论javascript中数组的声明.转换 ...

  2. javascript中的this与函数讲解

    前言 javascript中没有块级作用域(es6以前),javascript中作用域分为函数作用域和全局作用域.并且,大家可以认为全局作用域其实就是Window函数的函数作用域,我们编写的js代码, ...

  3. JavaScript 中的数据类型

    Javascript中的数据类型有以下几种情况: 基本类型:string,number,boolean 特殊类型:undefined,null 引用类型:Object,Function,Date,Ar ...

  4. javascript中的操作符详解1

    好久没有写点什么了,根据博主的技术,仍然写一点javascript新手入门文章,接下来我们一起来探讨javascript的操作符. 一.前言 javascript中有许多操作符,但是许多初学者并不理解 ...

  5. 掌握javascript中的最基础数据结构-----数组

    这是一篇<数据结构与算法javascript描述>的读书笔记.主要梳理了关于数组的知识.部分内容及源码来自原作. 书中第一章介绍了如何配置javascript运行环境:javascript ...

  6. javascript中变量提升的理解

    网上找了两个经典的例子 var foo = 1; function bar() { if (!foo) { var foo = 10; } alert(foo); } bar(); // 10 var ...

  7. 前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型

    前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型 前言(题外话): 有人说拖延症是一个绝症,哎呀治不好了.先不说这是一个每个人都多多少少会有的,也不管它究竟对生活有多么大的 ...

  8. 简单分析JavaScript中的面向对象

    初学JavaScript的时候有人会认为JavaScript不是一门面向对象的语言,因为JS是没有类的概念的,但是这并不代表JavaScript没有对象的存在,而且JavaScript也提供了其它的方 ...

  9. Javascript中的valueOf与toString

    基本上,javascript中所有数据类型都拥有valueOf和toString这两个方法,null除外.它们俩解决javascript值运算与显示的问题,本文将详细介绍,有需要的朋友可以参考下. t ...

  10. 关于javascript中的this关键字

    this是非常强大的一个关键字,但是如果你不了解它,可能很难正确的使用它. 下面我解释一下如果在事件处理中使用this. 首先我们讨论一下下面这个函数中的this关联到什么. function doS ...

随机推荐

  1. linux ln 命令使用参数详解(ln -s 软链接)(转)

    这是linux中一个非常重要命令,请大家一定要熟悉.它的功能是为某一个文件在另外一个位置建立一个同不的链接,这个命令最常用的参数是-s,具体用法是:ln -s 源文件 目标文件. 当 我们需要在不同的 ...

  2. jenkins构建java项目找不到命令mvn,java的解决方法

    jenkins构建java项目时出现的报错情况: $ mvn clean install FATAL: command execution failed java.io.IOException: er ...

  3. Dephi泛型

    TArray TEnumerator(抽象) TEnumerable(抽象) 实际使用:TList TQueue TStack TPair TDictionary ,内部都包含 TValueEnume ...

  4. layout_gravity和gravity的区别

    受不了了,用一遍查一遍...根本记不住,来这里记录一下 layout_gravity是子view相对于父view的位置,比如说,在button中设置了layout_gravity="cent ...

  5. 排序算法 C++代码实现

    插入排序: 就像摸牌,摸一张插进去,找一个哨兵.从第二个開始,和前一个比較.小的话前移一位. #include <iostream> #include<stdlib.h> us ...

  6. MongoDB 常见的查询索引

    常见的查询索引 _id索引         _id 索引是绝大多数集合默认建立的索引.对于每一个插入的数据.MongoDB 会自己主动生成一条唯一的 _id 字段. 1 2 3 4 5 6 7 8 9 ...

  7. SpringBoot Idea 启动报错 Process finished with exit code 1

    问题描述:没有其他任何错误日志,只有Process finished with exit code 1 问题原因:Maven POM.xml问题造成 由于是properties是我直接从其他项目中拷贝 ...

  8. ntp服务及其配置

    集群中使用NTP服务 简介 之前搭建zookeeper时报了一个错,我以为是ntp的问题,结果不是.这里详细学习一下如何在集群中使用ntp服务. 什么是ntp服务 来自ntp的百度百科: NTP服务器 ...

  9. 阿里云服务器---centos编译安装ffmpeg

    环境 系统环境:CentOS release 6.7 (Final) 需求 编译安装ffmpeg 获取依赖 安装依赖包 yum install -y autoconf automake cmake f ...

  10. Linux中crontab下scp文件传输的两种方式

    Linux下文件传输一般有两个命令scp.ftp(工具需要下载安装) 本文主要讲讲scp的文件传输脚本 1.scp ssh-keygen -t rsa免输入密码,传输 这里假设主机A 用来获到主机B的 ...