墙裂建议您在看这篇文章以前阅读一遍我以前写的文章 深刻浅出面向对象和原型【概念篇1】,由于此篇文章涉及到很多相关概念都在上篇文章里啦
对象是老生常谈的概念了,在这里咱们来简单复习一下segmentfault
var obj = { a: 1, b: "hello", c: true, d: function () { console.log("hello") }, e: { e_1: "对象内储存一个对象" } }
对象是一个储存一系列无序 key: value【键值对】 的集合的容器函数
注意:核心是要将对象做为一个容器看待
使用对象做为容器的这个特性咱们能够进行封装,这会产生两个好处this
new 运算符接受一个函数 F 及其参数:new F(arguments...)spa
function People(name) { this.name = name this.sayName = function () { console.log(name) } // 通常在这个函数里不要 return // 若是return引用类型的话,等于把return的值赋值给p1 } People() // this指向全局变量,name和sayName成为了全局变量的属性 var p1 = new People('sad') // 第一步:instance = {} 建立了一个类的实例 —— 空对象,而且将空的对象的__proto__属性设置为 F.prototype,也就是说 // 第二步:执行函数People(),并传入参数"sad",并将this指向p1 // 第三步:return instance【实例】 , 即把instance赋值给p1 // 请注意 People()是一个函数,new People()是构造函数 var p2 = new People('angry')
instance 的中文意思为 实例
那么 instanceof 天然就是用来判断对象是否为某个类型的实例prototype
console.log(p1 instanceof People) // true // 意思是判断 对象(p1)是否为某个类型(People)的实例 // p1 是由 People 构建出来的,天然是People的实例,返回为true
但须要注意的是,instanceof 运算符的工做原理是检测 类的prototype 是否存在实例的原型链上3d
console.log(p1 instanceof Object) // true // 由于Object.prototype能够被实例p1以原型链的方式访问到
构造函数在解决了上面全部问题,同时为实例带来了类型
但能够注意到在上例中,每一个的实例的方法做用是同样的
可是每一个实例被建立的时候都要从新声明一遍,浪费了内存code
// 咱们再来看一下这个函数 function People(name) { this.name = name this.sayName = function () { console.log(name) } // 每一个实例的sayName方法倒是相同的,并且每出现一个新实例,都是新声明一个函数,大大地浪费了内存 }
能不能给People的实例都使用同一个sayName方法呢对象
任何函数使用new表达式就是构造函数,也就是说这个函数成为了一个类blog
// 仍是这个例子 function People(name) { this.name = name this.sayName = function () { console.log(name) } } var p1 = new People('sad') var p2 = new People('angry') // People自己就有prototype属性 console.log(People.prototype) // {constructor: ƒ} // 而每一个对象也都会带有一个__proto__属性,指向这个构造函数【实例】的类 // 全部的实例都共用一个prototype console.log(p1.__proto__ === People.prototype) // true console.log(p2.__proto__ === People.prototype) // true
// 实例能够经过__prop__访问到其 类 的prototype属性,这就意味着类的prototype对象能够做为一个公共容器,供全部实例访问。 People.prototype.test = "abc" console.log(p1.test) // abc // p1这个对象没有test属性,可是能够经过它的__proto__属性访问到People的prototype属性
上述关系咱们用一张图来帮助你们更好地理解
由上咱们能够知道ip
prototype至关于全部实例均可以访问到的一个公共容器,这个公共容器也是这些实例的类的属性
那么如何解决内存浪费问题呢?
Answer:重复的东西移动到公共容器里就能够了
function People(name) { this.name = name // 每一个对象的name属性时不一样的,这点无可厚非 } People.prototype.sayName = function () { console.log(this.name) } // 将sayName方法放入People的原型中 var p1 = new People('sad') var p2 = new People('angry') console.log(p1.sayName()) console.log(p2.sayName())