# 原型链

# 1. 创建对象有几种方法

# 1)对象字面量方式(生成对象的原型链指向Object)

 - var o1={name: 'o1'}
 - var o2=new Object({name: 'o2'})

# 2) 使用显式的构造函数来创建对象

 ```
 var M=function(){this.name='name'}
 var 03=new M()
 ```

# 3)通过Object.create(),参数是一个对象,ta将作为新生成对象的原型对象

 ```
 var p={name: 'p'}
 var o4=Object.create(p)
 ```

# 2. 原型,构造函数,实例,原型链

  • 1)实例:无论是通过对象字面量,还是new Object(),还是通过构造函数的方式,生成的对象,都是一个实例
  • 2)构造函数:new关键字后面的函数,任何一个函数,只要被new使用了,都是一个构造函数,构造函数也是函数,拥有普通函数的特性
  • 3)构造函数可以使用new 运算符,来生成一个实例
  • 4)函数都有一个prototype属性,这是在函数声明的时候,js自动给ta加上去的,这个属性会自动初始化一个原型对象,这个原型对象还有一个constructor属性,指向该构造函数
  • 5)原型链:原型链就是,我从我的一个实例对象往上找构造这个实例的相关联的对象,然后这个关联的对象再往上找,它又有创造它的上一级的原型对象,以此类推,一直到Object.prototype原型对象终止,Object.prototype是原型链的顶端。(如果找到Object.prototype上还找不到,原路返回,告诉实例此方法或属性没有找到或者没有定义。如果说在中间的任意一个环节找到了,他就停止向上查找直接返回这个方法的用处)
  • 6)原型对象和原型链他们之间到底起什么作用?
    • 如果在构造函数里面用this添加很多方法或者属性,以后每个实例都会拷贝一份这个东西,会占用很多内存,我们可以把那些共用的方法都放在原型对象上,任何一个实例就可以通过他的原型链找到他上面的原型对象,原型对象上面的属性和方法,都是可以被实例共享的

# 3.instanceof 的原理

  • instanceof用于判断,某个实例对象是否为某个构造函数的实例,
  • instanceof本质,判断某个实例对象的__proto__属性和某个构造函数的prototype属性是否指向同一个引用地址

# 注意:

  • instanceof无法判断这个实例对象的直接构造函数是哪个,因为整条原型链上的构造函数都会对这个实例对象返回true
  • 要判断直接的构造函数,需要使用原型对象的constructor属性,它指向直接构造函数本身

# 4.关于原型和原型链的6个原型规则

  • 1.所有的引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性(除了“null”以外)
  • 2.所有的引用类型(数组、对象、函数),都有一个__proto__(我们约定它为隐式原型)属性,属性值是一个普通的对象
  • 3.所有的函数,都有一个prototype(我们约定它为显示原型)属性,属性值也是一个普通对象
  • 4.所有的引用类型(数组、对象、函数),proto(隐式原型)属性值指向它的构造函数的prototype(显示原型)属性值
  • 5.当试图得到一个对象(引用类型包括对象、数组、函数)的某个属性时,如果这个对象本身没有这个属性,那么会去它的__proto__(即它的构造函数的prototype)中寻找
  • 6.每个构造函数的prototype属性都有一个constructor属性,这个属性指向构造函数本身
var item;
for(item in f) {
  //高级浏览器已经在for in中屏蔽了来自原型的属性,但是这里建议大家还是加上这个判断,保证程序的壮健性
  if(f.hasOwnProperty(item)){ 
    console.log(item)
  }
}

# 5. new运算符

# 原理:

  • 1、一个新对象被创建。
  • 2、它继承自构造函数的原型对象(比如Foo.prototype)
  • 3、构造函数Foo被执行。执行的时候,相应的传参会被传入,同时上下文(this)会被指定为这个新实例。new Foo等同与new Foo(),只能用在不传递任何参数的情况。
  • 4、如果构造函数返回了一个“对象”,那么这个对象会取代整个new出来的结果。如果构造函数没有返回对象,那么new出来的结果为步骤一创建的对象。
var new1=function(F){
  var o=Object.create(F.prototype);
  var k=F.call(o);
  if(typeof k === 'object'){
    return k
  }else{
    return o
  }
}