js原型和构造函数
前言
从应用层面深入理解原型模式和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拥有了继承和多态的能力。
面向对象写法:定义普通函数做构造调用,在函数的原型上提供实例共享的属性和方法。
任务委托:将数据和工具对象分开定义,让工具对象作为数据对象的原型。达到数据和逻辑分离,将任务处理委托给其他对象的目的。
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原型和构造函数的更多相关文章
- 对js原型及构造函数的相关理解
一.js中的原型创建(声明)一个函数,浏览器在内存中会创建一个对象.每个函数都默认会有一个属性prototype指向了这个对象,就是说prototype的属性的值就是这个对象.此对象就是该函数的原型对 ...
- js原型和构造函数混合模式
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- JS原型、原型链、构造函数、实例与继承
https://cloud.tencent.com/developer/article/1408283 https://cloud.tencent.com/developer/article/1195 ...
- 一篇文章理解JS继承——原型链/构造函数/组合/原型式/寄生式/寄生组合/Class extends
说实在话,以前我只需要知道"寄生组合继承"是最好的,有个祖传代码模版用就行.最近因为一些事情,几个星期以来一直心心念念想整理出来.本文以<JavaScript高级程序设计&g ...
- JS中关于构造函数、原型链、prototype、constructor、instanceof、__proto__属性
在Javascript不存在类(Class)的概念,javascript中不是基于类的,而是通过构造函数(constructor)和原型链(prototype chains)实现的.但是在ES6中引入 ...
- Js中关于构造函数,原型,原型链深入理解
在 ES6之前,在Javascript不存在类(Class)的概念,javascript中不是基于类的,而是通过构造函数(constructor)和原型链(prototype chains)实现的.但 ...
- 简单粗暴地理解js原型链--js面向对象编程
原型链理解起来有点绕了,网上资料也是很多,每次晚上睡不着的时候总喜欢在网上找点原型链和闭包的文章看,效果极好. 不要纠结于那一堆术语了,那除了让你脑筋拧成麻花,真的不能帮你什么.简单粗暴点看原型链吧, ...
- JS原型链
JS作为发展了多年了对象语言,支持继承,和完全面向对象语言不同的是,JS依赖原型链来实现对象的继承. 首先JS的对象分两大类,函数对象和普通对象,每个对象均内置__proto__属性,在不人为赋值__ ...
- 【09-23】js原型继承学习笔记
js原型继承学习笔记 function funcA(){ this.a="prototype a"; } var b=new funcA(); b.a="object a ...
随机推荐
- loj#2269. 「SDOI2017」切树游戏
还是loj的机子快啊... 普通的DP不难想到,设F[i][zt]为带上根玩出zt的方案数,G[i][zt]为子树中的方案数,后面是可以用FWT优化的 主要是复习了下动态DP #include< ...
- POJ3261 Milk Patterns —— 后缀数组 出现k次且可重叠的最长子串
题目链接:https://vjudge.net/problem/POJ-3261 Milk Patterns Time Limit: 5000MS Memory Limit: 65536K Tot ...
- matlab之sortrows()函数
sortrows()函数的格式: sortrows(A,column) A是一个矩阵,如果没有第二个参数column,则默认按照第一列升序排列,如果遇到重复数字,则按照第二列升序排列,依次类推... ...
- PHP闭包详解
匿名函数 提到闭包就不得不想起匿名函数,也叫闭包函数(closures),貌似PHP闭包实现主要就是靠它.声明一个匿名函数是这样: $func = function() { }; //带结束符 可以看 ...
- 岭回归与Lasso回归
线性回归的一般形式 过拟合问题及其解决方法 问题:以下面一张图片展示过拟合问题 解决方法:(1):丢弃一些对我们最终预测结果影响不大的特征,具体哪些特征需要丢弃可以通过PCA算法来实现:(2):使用正 ...
- leetcode 290 Word Pattern(map的应用)
Given a pattern and a string str, find if str follows the same pattern. Here follow means a full mat ...
- 网络编程学习笔记-全零网络IP地址0.0.0.0详谈
RFC: - Addresses in this block refer to source hosts on "this" network. Address may be use ...
- python定时任务:apscheduler的使用(还有一个celery~)
文章摘自:https://www.cnblogs.com/luxiaojun/p/6567132.html 1 . 安装 pip install apscheduler 2 . 简单例子 # codi ...
- Java多线程加强
一.传统多线程 public void start() Causes this thread to begin execution; the Java Virtual Machine calls th ...
- python使用uuid生成唯一id或str
介绍: UUID是128位的全局唯一标识符,通常由32字节的字符串表示. 使用: import uuid print uuid.uuid1() 14bfe806-f1c7-11e6-83b5-0680 ...