原型和原型链
一般会问的问题:
- 创建对象有几种方法
- 原型、构造函数、实例、原型链
- instanceof 的原理
- new 运算符
创建对象有几种方法
原型关系
- 每个class(class 实际是函数,是语法糖)都有显示原型 prototype
- 每个实例都有隐式原型 __proto__
- 实例的 __proto__ 指向对应class 的 prototype
基于原型的执行规则
- 获取属性 xialuo.name 或执行方法 xialuo.sayhi() 时
- 先在自身属性和方法寻找
- 如果找不到则自动去 __proto__ 中寻找
原型、构造函数、实例、原型链
- 原型链:从一个实例对象往上找构造这个实例的相关联的对象,然后这个关联的对象再往上找它又有创造它的上一级的原型对象,以此类推,一直到 Object.prototype 原型对象终止,这个链条就断了,也就是说 Object.prototype 是整个原型链的顶端。通过什么往上找?就是通过 prototype 和 __proto__.
- 原型:构造函数都有一个 prototype 属性,这是在声明一个函数时js 自动增加的,这个 prototype 指的就是原型对象。原型对象怎么区分被哪个构造函数引用?就是通过 constructor(构造器),原型对象中会有一个构造器,这个构造器会默认声明的那个函数。
- 构造函数:任何一个函数只要被 new 去操作(使用)就是构造函数,构造函数也是函数
- 实例:只要是对象就是一个实例
- 构造函数可以使用new 生成实例
通过原型链的方式找到原型对象,原型对象的方法是被不同的实例所共有的,这就是原型链的一个工作原理
1、构造函数(函数)才有propotype 的,对象没有 propotype,
2、只有实例对象有 __proto__的,函数既是函数又是对象
原型链
- 如果实例中有自身属性则直接使用自身的属性(如图中 xialuo),如果没有则会再自身的隐式原型链中去找,一直找到最顶级 Object 为止,如果都找不到,则最后返回的null
- 每个构造函数都有一个显示原型prototype (如 Student, People),且每个显示原型都会对应有一个隐式原型__proto__,而他的隐式原型的父级又有个显示原型,他们都是一级级往上找的,然后一直找到树形结构的第一层(Object)为终点
- instanceof 是为判断此实例或构造函数是否是父级继承的,如(xialuo instanceof People // true, xialuo instanceof Array // false)
instanceof 原理:
实例对象的 __proto__ 和构造函数本身没有什么关联,它关联的是构造函数 prototype 下面的一个属性即 prototype 所引用的原型对象
是判断 实例对象.__proto__ 和 构造函数.prototype是不是一个引用(即引用同一个地址)
new 运算符
new 构造函数的原理:
生成一个空对象(Object.create)
将空对象的__proto__指向构造函数的prototype var o = Object.create(func.prototype)
执行构造函数,this 上下文指向空对象 var k = func.call(o)
若构造函数返回的是对象,那么这个对象将取代原来的空对象
if(typeof k === 'object') {
return k
} else {
return o
}
题目
如何准确判断一个变量是不是数组?
答案:用 instanceof, 如 a instanceof Array
手写一个简易的 jQuery,考虑插件和扩展性
1 class jQuery { 2 constructor(selector) { 3 const result = document.querySelectorAll(selector) 4 const length = result.length 5 for(let i = 0; i < length; i++) { 6 this[i] = result[i] 7 } 8 this.length = length 9 this.selector = selector 10 } 11 get(index) { 12 return this[index] 13 } 14 each(fn) { 15 for(let i = 0; i < this.length; i++) { 16 const elem = this[i] 17 fn(elem) 18 } 19 } 20 21 on(type, fn) { 22 return this.each(elem => { 23 elem.addEventlistener(type, fn, false) 24 }) 25 } 26 } 27 28 jQuery.propotype.dialog = function(info) { 29 alert(info) 30 } 31 32 class myJQuery extends jQuery { 33 constructor(selector) { 34 supper(selector) 35 } 36 addClass(className) { 37 } 38 style(data) { 39 } 40 }
class的原型本质,怎么理解?
答案:
- 上面原型和原型链的图示
- 属性和方法的执行规则