一. 知识点
-
构造函数
-
构造函数 - 扩展
-
原型规则和示例
-
原型链
- 构造函数
我们通过 new 然后把需要的参数传递进入,这个相信大家都看得懂,这边主要有一个值得注意的函数最后一行 return this; 这个不管你写没写,js默认都会返回 this 给 f,所以 f 就有 name 和 age 的属性。
- 构造函数 - 扩展
真题:判断一个变量是否为"数组"
我们可以通过 变量 instanceof Array 来判断
复制代码
- 原型规则和示例
5条原型规则,原型规则是学习原型链的基础
3.1)所有的引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性(除了"null"以外) 什么是自由扩展属性,请看下面代码:
3.2)所有的引用类型(数组、对象、函数),都有一个_proto_属性(隐式原型),属性值是一个普通的对象
3.3)所有的函数,都有一个prototype(显式原型)属性,属性值也是一个普通对象
3.4)所有的引用类型(数组、对象、函数),_proto_属性值指向它的构造函数的"prototype"属性值
3.5)当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的__proto__(即它的构造函数的prototype)中寻找。
第5行,通过前面的规则可知所有函数有都一个prototype(显式原型)属性,然后我们通过prototype 扩展一个 alerName 的方法。
第9行,通过 Foo 实例化一个对象,第10行跟上面一样这个也好理解,扩展了一个 printName 的方法。
第14行 我们调用 printName 打印了zhangsan 这个值。
第15行 我们调用 alerName 时就验证了第5条规则(如果这个对象本身没有这个属性,那么会去它的__proto__(即它的构造函数的prototype)中寻找),我们实现 f 对象有一个 显式原型 prototype扩展的alerName, 这个根据规则4我们知道,f的隐式原型__proto__指向它的显示原型,那我们执行第15行的时候,f 本身没有alerName方法,那它就会去 f 的隐式原型 __proto__去找,alerName已经被 f 的显示原型扩展了,所以最终会调用 alertName 方法。
二.原型链
对上面的例子,我们多了第16行,f.toString(),它的执行是怎么样的呢?
执行这个函数我们根据第五个规则来想,如果对象没有这个属性的时候,就会去它的隐式原型__proto__去找,它自己的隐式原型就是构造函数显式原型,就是从Foo.prototype去找。然后Foo.prototype中并没有toString这个东西,但是Foo.prototype它也是个对象,它也是个对象,它也是个对象(重要的事说三遍),然后在它中去打toStirng这个方法,那是不是也是向它的隐式原型去找
直角表示是构造函数,圆角表示对象
从上图分析:Foo 是一个构造函数,new 出了一个对象 f, f 有一个隐式原型 proto 指向 Foo.protoype 显式原型,但是 Foo.prototype 它也是个对象,它这个对象的构造函数是Object,Object也是个函数,也有一个显示原型。
prototype,Object.prototype是个对象,但是这边有个特例,,,Object.prototype 的隐式类型是一个Null,这是js为防止死循环做的特例。所以在看上面的第16行 f.toString() 它先从Foo.prototype找,找不到再从隐式的Object.prototype找,找到Object中有个toString方法,就执行了这个方法。
instanceof 用于判断引用类型属于哪个构造函数的方法
三.真题
题目一:如何准备判断一个变量是数组类型
题目二:写一个原型链继承的例子
这里是一个基础的例子,先理解明白,但在面试中最好不要这么写,人家跟你说写一个原型链继承的例子,你上来冒出一堆动物显得特别low,所以说这个地方你首先要搞明白。推荐更加贴近实站的原型继承示例请看题目四。
题目三:描述new一个对象的过程
题目四:写一个封装DOM 的查询的例子
愿你成为终身学习者