前言

  从应用层面深入理解原型模式和js中的构造函数。

构造函数(constructor)

  js中的任何对象都有自己的构造函数。js中使用字面量声明的普通对象({})或数组([])等子对象本质上都是使用相关的函数做构造调用声明的。

// 等同于 var obj = {};
var obj = new Object();
// 等同于 arr = [];
var arr = new Array();

  获取对象的构造函数:constructor是可读的,在对象上进行普通的属性访问(. / [])即可。

// 这里我们可以看到字面量语法声明的对象本质还是使用Object()构造的。var obj = {};
console.log(obj.constructor); // ƒ Object() { [native code] }

原型

  显式原型prototype属性

    prototype是函数的属性。每个函数被创建之后,都会拥有一个prototype属性,这个属性指向函数的原型对象。

function fn (){}
console.log(fn.prototype); 

    fn.prototype的原型在chrome下的输出。是一个对象,这个对象有一个显式的属性constructor(构造函数),它指向的是构造这个对象的函数。 还有一个隐式的属性,__proto__。

  隐式原型__proto__属性

    __proto__是对象的属性。每个对象被创建的时候都会拥有这个属性,这个属性指向的是,构造这个对象的函数的原型对象。

    访问对象的__proto__属性:IE10以前无法识别__proto__属性,其他浏览器大部分都可以识别,可以输出但无法访问内部信心。ES5提供的Object.getPtotypeOf(obj) 可以获取指定对象的__proto__属性。

function fn (){}
var obj = new fn();
console.log(fn.prototype === Object.getPrototypeOf(obj)); // true

搞清楚prototype/__proto__/constructor之间的区别和联系

  1,所有对象都有自己的构造函数(constructor),和一个隐式的原型属性(__proto__),__proto__指向的是这个对象的构造函数的原型。

  2,所有的函数都有一个prototype属性这个熟悉指向的是构造函数的原型对象。

var obj = {};
// 这里的true不理解的话回头再看一遍之前的小例子,敲一下。理解这个true的话 原型这个部分的应用就没问题了。
console.log(obj.constructor.prototype === Object.getPrototypeOf(obj)); // true

原型链

  原型链就是一个对象作为另一个对象的原型而存,而这个作为别人原型的对象还有自己的原型。

  根对象

    js中的所有对象都拓展于Object.prototype。 它是js中的顶层对象。在它之上没有其他的原型了。

var obj= {};
var objConstructor = obj.constructor;
// Object() 是使用js字面量创建的对象的构造函数。
console.log(objConstructor); // ƒ Object() { [native code] }
// Object.prototype是js中的根对象,在它之上没有其他原型了。
console.log(Object.getPrototypeOf(objConstructor.prototype)); // null

  原型链的形成
    关键就在于让一个对象成为另一个对象的原型。

    Object.create(obj):返回一个把指定参数作为原型的新对象。 

var obj= {name:"obj"};
var newObj = Object.create(obj);
console.log(newObj);

    从chrome下的输出我们可以看到 形成了一个三层的原型链 newObject 中的隐式原型属性__proto__指向了obj,obj是使用字面量创建的普通对象,它本质上是使用Object()创建的。所以它指向的是根对象Object.prototype。

    

原型模式的执行流程

  在对象本身查找要访问的属性和方法,如果没有,就到最近的原型上找,直接原型上没有,就到原型的原型上找,找到就直接返回,结束查找。一直找到Object.prototype上都没有,就返回undefined。

原型模式的应用

  主要有两种,面向对象写法和任务委托写法。面向对象就是使用原型继承,多态都用的很少,使用起来也比较难理解。任务委托是在《你不知道的js》一书中看到的写法,设计上来看比强行面向对象要直观。但现在时代变了,ES6提供了Class语法糖,让面向对象的js程序可读性较好,便于理解。所以只了解一下任务委托写法。

面向对象

  三大特征:封装,继承,多态。

  好处:结构清晰,易维护,易拓展。

基于原型继承的面向对象

  js中是没有传统面向类语言中的类和构造函数的,它使用new关键字配合普通函数模拟了构造函数,使用原型模拟类,让js拥有了继承和多态的能力。

  面向对象写法:定义普通函数做构造调用,在函数的原型上提供实例共享的属性和方法。

function Banner(info){
  this.ele = info.ele;
}
Banner.prototype = {
  constructor:Banner,
  say:function(){
  console.log("我是定义在Banner原型上的方法,由所有Banner构造出来的对象共享!");
  return this;
},
show:function(){
  console.log(this.ele);
  return this;
  }
}
new Banner({
ele:"box"
}).say().show();

  任务委托:将数据和工具对象分开定义,让工具对象作为数据对象的原型。达到数据和逻辑分离,将任务处理委托给其他对象的目的。

var util = {
  say:function(){
    console.log(this.name);
  }
}
var data = Object.create(util);
data.name = "键盘";
data.say(); // 键盘

小结:

  1,每个对象都有自己的构造函数,可以通过constructor属性访问到。

  2,每个对象都有一个隐式原型属性__proto__,可以使用Object.getPrototypeOf(obj)访问。

  3,每个函数都有自己的原型对象,可以通过prototype属性访问。

  4,对象的隐式原型属性(__proto__)指向的就是它的构造函数的原型(prototype)。

  5,所有使用字面量创建的对象,本质上都是使用相关构造器函数构造出来的,函数是(Function()),数组是(Array())等等。

  6,js中的Object是顶层函数它的prototype之上没有其他的原型了。js中所有对象的原型链的顶层几乎都是Object.prototype。

  7,原型链就是对象做为其他对象的原型,的同时还有自己的原型。

  8,原型模式的执行顺序就是首先在对象自有属性中查找,找不到就问原型有没有,原型没有就问原型的原型有没有,直到找到返回或找到顶层原型后返回undefined。

  9,js中的面向对象就是基于原型模式在普通函数的原型上定义共享的属性和方法,达到继承的目的。

js原型和构造函数的更多相关文章

  1. 对js原型及构造函数的相关理解

    一.js中的原型创建(声明)一个函数,浏览器在内存中会创建一个对象.每个函数都默认会有一个属性prototype指向了这个对象,就是说prototype的属性的值就是这个对象.此对象就是该函数的原型对 ...

  2. js原型和构造函数混合模式

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. JS原型、原型链、构造函数、实例与继承

    https://cloud.tencent.com/developer/article/1408283 https://cloud.tencent.com/developer/article/1195 ...

  4. 一篇文章理解JS继承——原型链/构造函数/组合/原型式/寄生式/寄生组合/Class extends

    说实在话,以前我只需要知道"寄生组合继承"是最好的,有个祖传代码模版用就行.最近因为一些事情,几个星期以来一直心心念念想整理出来.本文以<JavaScript高级程序设计&g ...

  5. JS中关于构造函数、原型链、prototype、constructor、instanceof、__proto__属性

    在Javascript不存在类(Class)的概念,javascript中不是基于类的,而是通过构造函数(constructor)和原型链(prototype chains)实现的.但是在ES6中引入 ...

  6. Js中关于构造函数,原型,原型链深入理解

    在 ES6之前,在Javascript不存在类(Class)的概念,javascript中不是基于类的,而是通过构造函数(constructor)和原型链(prototype chains)实现的.但 ...

  7. 简单粗暴地理解js原型链--js面向对象编程

    原型链理解起来有点绕了,网上资料也是很多,每次晚上睡不着的时候总喜欢在网上找点原型链和闭包的文章看,效果极好. 不要纠结于那一堆术语了,那除了让你脑筋拧成麻花,真的不能帮你什么.简单粗暴点看原型链吧, ...

  8. JS原型链

    JS作为发展了多年了对象语言,支持继承,和完全面向对象语言不同的是,JS依赖原型链来实现对象的继承. 首先JS的对象分两大类,函数对象和普通对象,每个对象均内置__proto__属性,在不人为赋值__ ...

  9. 【09-23】js原型继承学习笔记

    js原型继承学习笔记 function funcA(){ this.a="prototype a"; } var b=new funcA(); b.a="object a ...

随机推荐

  1. Android Wifi简单的梳理【转】

    本文转载自:http://blog.csdn.net/gabbzang/article/details/10005411 代表一个已经配置过的网络.包含网络ID(networkId).该网络ID代表的 ...

  2. 简单的可兼容所有浏览器的操作html元素的javascript框架

    1.根据id名称取元素  $id(idName) 2.根据class定义取元素  $class(className)返回所有class被定义成className的元素数组,或者$Eclass(clas ...

  3. [干货]兼容HTML5的Placeholder属性-更新版v0.10102013

    HTML5对Web Form做了许多增强,比如input新增的type类型.Form Validation等.Placeholder是HTML5新增的另一个属性,当input或者textarea设置了 ...

  4. 日期时间选择器bootstrap-datetimepicker表单组件

    Bootstrap受到很多人的喜欢,它不仅拥有一套完整漂亮的UI,而且爱好者们为其开发扩展了很多有用的插件和主题!让其拥有无限可能! 今天为开发者推荐一款强大,易用的时间日历插件——bootstrap ...

  5. 分享知识-快乐自己:SpringMVC 底层执行原理解析

    底层实现原理图: 观看底层代码: 1):打开 web.xml 文件  2):按住 Ctrl + 鼠标左键 进入底层查看源码   3):按住 Ctrl+o 找到对应的方法doDispatch   5): ...

  6. Go丨语言对数据库操作报错 panic: dial tcp 127.0.0.1:3306: connectex: No connection could be made because the target machine actively refused it.

    panic: dial tcp 127.0.0.1:3306: connectex: No connection could be made because the target machine ac ...

  7. appium 特殊操作

      一.触摸操作   1.driver.tap([坐标],持续点击时间) 除了定位到元素的点击外,也可以通过tab实现坐标的点击 driver.tap(driver.tap([(216,1776)], ...

  8. 【LintCode】060.Search Insert Position

    题目: Given a sorted array and a target value, return the index if the target is found. If not, return ...

  9. Redo Gap 处理与优化

    理论背景 当redo data 传送发生中断时就会产生redo gap.当redo 传送恢复正常以后,redo transport service 会自动检测redo gap并发送缺失的redo 到d ...

  10. Oracle中的float类型字段

    Oracle中的float类型对应着C#中的decimal类型