原型和原型链
这部分主要涉及六以下知识点:
- 构造函数
- 构造函数扩展
- 原型规则和示例
- 原型链
- instanceof
原型——[[prototype]],是js中的对象的一个特殊的内置属性
强调:JavaScript中只有对象,没有类!
下面的代码是一个对象创建的例子
function Foo(name, age) { // 默认大写首字母为构造函数,自己写代码也需要遵守
this.name = name
this.age = age
this.class = 'class-1'
// return this // 默认有这一句话,推荐不写
}
var f = new Foo('zhangsan', 20)
var f1 = new Foo('abc', 21)
对于原型而言,共有5条规则:
1 所有的引用类型(数组,对象,函数)都具有对象特性,即可以*扩展属性
var obj = {}
obj.a = 100
var arr = []
arr.a = 100
function fn(){}
fn.a = 100
2 所有的引用类型(数组,对象,函数)都有一个’__proto__’属性,属性值是一个普通的对象
console.log(obj.__proto__)
console.log(arr.__proto__)
console.log(fn.__proto__)
// output
{}
[]
[Function]
3 每个构造函数有一个prototype属性,属性值也是一个普通的对象
console.log(obj.prototype)
console.log(arr.prototype)
console.log(fn.prototype)
// output
undefined
undefined
fn(){}
4 所有的引用类型(数组,对象,函数)的’__proto__’属性值都指向它的构造函数的prototype的属性值(这句话不完全正确,有特殊情况,但是不必刻意讨论)
console.log(obj.__proto__ === Object.prototype)
console.log(arr.__proto__ === Array.prototype)
console.log(fn.__proto__ === Function.prototype)
// output
true
true
true
5 当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的’__proto__’中寻找
function Foo(name, age) {
this.name = name
}
Foo.prototype.alertName = function() {
alert(this.name)
}
var f = new Foo('zhangsan')
f.printName = function() {
console.log(this.name)
}
f.printName()
f.alertName()
console.log(f.__proto__)
console.log(f.prototype)
// output
zhangsan //(console.log)
zhangsan //(alert)
Foo { alertName: [Function] }
undefined
下面的图是关于__proto__的一张图,是我自己画的,仅用于理解__proto__
最后总结一下_proto__和prototype的知识点
在原型的知识点方面,要注意最重要的是__proto__,而不是prototype,因为prototype只是在函数中才存在的,而__proto__是在所有的对象中都存在的。
此外判断原型继承时,要通过new操作符的使用来判断。也就是如果
var a = new A
或者
var a = new A() // 我觉得还是这种写法比较标准,虽然上面那种并不会报错,也见到有人用过,但是看起来不习惯,有可能造成误解
那么a的原型就是A,在程序代码方面,a.__proto__就是A.prototype。这个说法很奇怪,但是就是这么规定的,因此如果a中无法找到是属性,例如a.name,就要在A.prototype中去找,注意是A.prototype而不是A!
题目六:如何准确判断一个变量是数组类型
var arr = []
arr instanceof Array // true
typeof arr // object
typeof操作符:用于检测给定变量的数据类型,返回结果是个字符串:未定义,布尔值,字符串,数字,对象,函数。注意:并不包括数组这种类型的结构,别搞混了!
- “undefined”这个值未定义
- “boolean”
- “string”
- “number”
- “object”
- “function”
instanceof:中文意思是“实例”
用于判断a是否为A的实例,即: a instanceof A
所以如果需要判断一个变量是否为数组,则应该使用: a instanceof Array
最后举一个例子,说明一下 “object” 和Object的用法区别:
var a = {
name: "wufan"
}
console.log(typeof a) //"object"
console.log(a instanceof Object) // true
// console.log(a instanceof object) //这句话不符合语法规则,会报错,注意Object和object的区别
题目七:写一个原型链继承的例子
参照上面图中代码即可
题目八: 描述new一个对象的过程
- 创建一个新对象
- 这个新对象会被执行[[prototype]]连接
- this指向这个新对象,即被绑定在函数调用的this
- 如果函数没有返回其他对象,那么将会默认返回this指向的新对象
题目九: zepto(或其他框架)源码中如何使用原型链
阅读源码是高效提升技能的方式,但是不能埋头苦钻,多看源码分析的文章,有目的性的去理解源码