我们创建的每个函数都有一个 prototype (原型)属性,这个属性是一个指针,指向一个原型对象,而这个原型对象中拥有的属性和方法可以被所以实例共享。

function Person(){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
person1.sayName(); //"Nicholas"
var person2 = new Person();
person2.sayName(); //"Nicholas"
alert(person1.sayName == person2.sayName); //true

一、理解原型对象

无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个 prototype属性,这个属性指向函数的原型对象。

在默认情况下,所有原型对象都会自动获得一个 constructor(构造函数)属性,这个属性包含一个指向 prototype 属性所在函数的指针。

当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部属性),指向构造函数的原型对象。ECMA-262 第 5 版中管这个指针叫 [[Prototype]] 。

虽然在脚本中没有标准的方式访问 [[Prototype]] ,但 Firefox、Safari 和 Chrome 在每个对象上都支持一个属性__proto__ ;而在其他实现中,这个属性对脚本则是完全不可见的。

不过,要明确的真正重要的一点就是,这个连接存在于实例与构造函数的原型对象之间,而不是存在于实例与构造函数之间。

以前面使用 Person 构造函数和 Person.prototype 创建实例的代码为例,图 6-1 展示了各个对象之间的关系。

在此, Person.prototype 指向了原型对象,而 Person.prototype.constructor 又指回了 Person 。

person1 和 person2 都包含一个内部属性,该属性仅仅指向了 Person.prototype ;换句话说,它们与构造函数没有直接的关系。

可以调用 person1.sayName() 。这是通过查找对象属性的过程来实现的。(会先在实例上搜索,如果搜索不到就会继续搜索原型。)

用isPrototypeOf()方法判断实例与原型对象之间的关系
alert(Person.prototype.isPrototypeOf(person1)); //true
alert(Person.prototype.isPrototypeOf(person2)); //true 用Object.getPrototypeOf() 方法返回实例的原型对象
alert(Object.getPrototypeOf(person1) == Person.prototype); //true 使用 hasOwnProperty() 方法可以检测一个属性是存在于实例中,还是存在于原型中。
alert(person1.hasOwnProperty("name")); //false  来着原型
person1.name = "Greg";
alert(person1.name); //"Greg"——来自实例
alert(person1.hasOwnProperty("name")); //true

二、更简单的原型语法

前面例子中每添加一个属性和方法就要敲一遍 Person.prototype 。为减少不必要的输入,也为了从视觉上更好地封装原型的功能,更常见的做法是用一个包含所有属性和方法的对象字面量来重写整个原型对象。

function Person(){
}
Person.prototype = {
  name : "Nicholas",
  age : 29,
  job: "Software Engineer",
  sayName : function () {
    alert(this.name);
  }
};

在上面的代码中,我们将 Person.prototype 设置为等于一个以对象字面量形式创建的新对象。最终结果相同,但有一个例外: constructor 属性不再指向 Person 了。

前面曾经介绍过,每创建一个函数,就会同时创建它的 prototype 对象,这个对象也会自动获得 constructor 属性。

var friend = new Person();
alert(friend instanceof Object); //true
alert(friend instanceof Person); //true
alert(friend.constructor == Person); //false
alert(friend.constructor == Object); //true

在此,用 instanceof 操作符测试 Object 和 Person 仍然返回 true ,但 constructor 属性则等于 Object 而不等于 Person 了。

如果 constructor 的值真的很重要,可以像下面这样特意将它设置回适当的值。

function Person(){
}
Person.prototype = {
constructor : Person,
name : "Nicholas",
age : 29,
job: "Software Engineer",
sayName : function () {
alert(this.name);
}
};

三、原生对象的原型

所有原生引用类型( Object 、 Array 、 String ,等等)都在其构造函数的原型上定义了方法。

例如,在 Array.prototype 中可以找到 sort() 方法,而在 String.prototype 中可以找到substring() 方法。尽管可以这样做,但不推荐修改原生对象的原型。

四、原型对象的问题

原型模式的最大问题是由其共享的本性所导致的。 修改其中的一个,另一个也会受影响。

function Person(){
}
Person.prototype = {
constructor: Person,
name : "Nicholas",
age : 29,
job : "Software Engineer",
friends : ["Shelby", "Court"],
sayName : function () {
alert(this.name);
}
};
var person1 = new Person();
var person2 = new Person();
person1.friends.push("Van");
alert(person1.friends); //"Shelby,Court,Van"
alert(person2.friends); //"Shelby,Court,Van"
alert(person1.friends === person2.friends); //true

五、原型链

其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。然后层层递进,就构成了实例与原型的链条,这就是所谓原型链的基本概念。

function SuperType(){
  this.property = true;
}
SuperType.prototype.getSuperValue = function(){
  return this.property;
};
function SubType(){
  this.subproperty = false;
}
//继承了 SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function (){
  return this.subproperty;
};
var instance = new SubType();
alert(instance.getSuperValue()); //true

 一张图说明:

property 则位于 SubType.prototype 中。这是因为 property 是一个实例属性,而 getSuperValue() 则是一个原型方法。既然 SubType.prototype 现在是 SuperType的实例,那么 property 当然就位于该实例中了。

javascript 原型及原型链详解的更多相关文章

  1. JavaScript作用域及作用域链详解、声明提升

    相信大家在入门JavaScript这门语言时对作用域.作用域链.变量声明提升这些概念肯定会稀里糊涂,下面就来说说这几个 Javascript 作用域 在 Javascript 中,只有局部作用域和全局 ...

  2. 你不知道的JavaScript--Item15 prototype原型和原型链详解

    用过JavaScript的同学们肯定都对prototype如雷贯耳,但是这究竟是个什么东西却让初学者莫衷一是,只知道函数都会有一个prototype属性,可以为其添加函数供实例访问,其它的就不清楚了, ...

  3. JavaScript对象的property属性详解

    JavaScript对象的property属性详解:https://www.jb51.net/article/48594.htm JS原型与原型链终极详解_proto_.prototype及const ...

  4. javascript中=、==、===区别详解

    javascript中=.==.===区别详解今天在项目开发过中发现在一个小问题.在判断n==""结果当n=0时 n==""结果也返回了true.虽然是个小问题 ...

  5. Javascript 调试利器 Firebug使用详解

    Javascript 调试利器 Firebug使用详解 有时候,为了更清楚方便的查看输出信息,我们可能需要将一些调试信息进行分组输出,那么可以使用console.group来对信息进行分组,在组信息输 ...

  6. JavaScript中return的用法详解

    JavaScript中return的用法详解 最近,跟身边学前端的朋友了解,有很多人对函数中的this的用法和指向问题比较模糊,这里写一篇博客跟大家一起探讨一下this的用法和指向性问题. 1定义 t ...

  7. “全栈2019”Java异常第十五章:异常链详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java异 ...

  8. javascript 中合并排序算法 详解

    javascript 中合并排序算法 详解 我会通过程序的执行过程来给大家合并排序是如何排序的...  合并排序代码如下: <script type="text/javascript& ...

  9. javascript中的this作用域详解

    javascript中的this作用域详解 Javascript中this的指向一直是困扰我很久的问题,在使用中出错的机率也非常大.在面向对象语言中,它代表了当前对象的一个引用,而在js中却经常让我觉 ...

  10. JavaScript中this的用法详解

    JavaScript中this的用法详解 最近,跟身边学前端的朋友了解,有很多人对函数中的this的用法和指向问题比较模糊,这里写一篇博客跟大家一起探讨一下this的用法和指向性问题. 1定义 thi ...

随机推荐

  1. String类为什么是final的

    首先我们使用new创建一个String对象的时候比如: String str=new String("123"); 这句话里面创建了两个对象,第一个在系统中创建了一个"a ...

  2. 用Putty通过SSH访问Linux服务器

    1,sudo apt-get install ssh 2,sudo service ssh restart 3,重启ssh成功后,就可以直接用Putty访问服务器.

  3. Centos下安装php扩展sphinx

    官方地址:http://pecl.php.net/package/sphinx wget http://pecl.php.net/get/sphinx-1.3.3.tgz tar -zxvf sphi ...

  4. windows 下 Symfony的下载与安装

    初始化项目 本篇教程我尽量按照Windows/*nix都可以运行的方式来讲解. 得益于Symfony installer,我们目前可以很方便的初始化一个Symfony2项目.不过首先,你得有一个Sym ...

  5. C#中await和async关键字的简单理解

    C# 5.0之后,为了简化异步编程,引入了异步函数的概念,也就是方法标记async,然后可以使用await表达式来等待异步操作返回. await关键字看起来是一个阻塞线程的调用,但是实际上执行到awa ...

  6. HDU - 3038 种类并查集

    思路:种类并查集的每个节点应该保存它的父节点以及他和父节点之间的关系.假设root表示根结点,sum[i-1]表示i到根结点的和,那么sum[j-1] - sum[i]可以得到区间[j, i]的和.那 ...

  7. CodeForces-748D 贪心

    这题的思维难度不是很大,属于编程实现细节处理较多的题. 暂且把每个字符串的"beauty"称为魅力值,用一个优先队列数组将同一个字符串的所有魅力值保存,通过map将不同字符串编号, ...

  8. http缓存(http caching)

    通过使用缓存web网站和web应用的性能能够得到显著的提升.Web caches能够减小延迟和网络流量,从而缩短展示资源所花费的时间. 在http中控制缓存行为的首部字段是Cache-Control, ...

  9. mysql学习笔记03 mysql数据类型

    数值型:整数型 小数型字符串型时间和日期类型 数值型①整数型1 2 3 4 81bin表示1位,1Byte表示一个字节1B=8b.1汉字=2字节(1 word = 2 byte)1字节=8位(1 by ...

  10. Nginx学习笔记3--Nginx和PHP(fastCGI)的配置和优化

    php和nginx的配置 server{ root html; listen 80; server_name a.com; index index.php index.html ; location ...