理解 JavaScript 原型 / 原型链
关于对象
以下代码中 p
的值是一个新对象,里面拥有 name
和 age
属性
function People(name, age){ this.name = name this.age = age } var p = new People('evenyao', 27)
下面代码得到的结果同理,因为 return 的是一个 “非对象”
function People(name, age){ this.name = name this.age = age return 'hello' } var p = new People('evenyao', 27)
如果是下面代码, p
的值为一个新对象,里面拥有 a
和 b
属性
function People(name, age){ this.name = name this.age = age return {a: 1, b: 2} } var p = new People('evenyao', 27)
new
function Person(name) { this.name = name this.sayName = function() { console.log('say name...') } } var p = new Person('evenyao')
以上代码的执行过程如下:
- 执行 new Person
- 创建一个空对象 {},假设名字是 tmpObj
- 执行 Person 函数,执行过程中对 this 操作就是对 tmpObj 进行操作
- 函数执行完后返回刚刚创建的 tmpObj
- 把 tmpObj 赋值给 p (p也指向同一个对象)
instanceof
instanceof 是一个操作符,可以判断对象是否为某个类型的实例
构造函数
function Person(nick,age){ this.nick= nick this.age = age this.printName = function(){ console.log('say name...') } } var p1 = new Person('Byron',20) var p2 = new Person('Casper',25) //p1.printName() //p2.printName()
图示可以看出,实例可以通过 __prop__
访问到其类型的 prototype
属性,这就意味着类的 prototype
对象可以作为一个公共容器,供所有实例访问。
抽象重复
//按照原型链的写法 使用公共容器 function Person(nick,age){ this.nick= nick this.age = age } Person.prototype.sayName = function(){ console.log('say name...') } var p1 = new Person('Byron',20) var p2 = new Person('Casper',25) // p1.sayName() `Byron` // p2.sayName() `Casper`
这时候对应的关系是这样的
原型链
JS 在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做 __proto__
的内置属性,用于指向创建它的函数对象的原型对象 prototype
。在访问一个对象属性的时候,如果对象本身没有找到这个属性,就会沿着原型链一层一层的寻找。
总结原型
这三句话能解释一切关于原型方面的问题
-
当
new
一个函数的时候会创建一个对象,『函数.prototype
』 等于 『被创建对象.__proto__
』 -
一切函数都是由
Function
这个函数创建的,所以『Function.prototype
===被创建的函数.__proto__
』 -
一切函数的原型对象都是由
Object
这个函数创建的,所以『Object.prototype
===一切函数.prototype.__proto__
』
举例
案例1
扩展 String 的功能增加 reverse 方法,实现字符串倒序
var str = 'hello evenyao' var str2 = str.reverse() console.log(str2) // 'oayneve olleh'
即在String
的prototype
上添加 关于reverse
的function
,然后再调用 reverse()
String.prototype.reverse = function(){ return this.split("").reverse().join("") console.log(this) } var str = 'hello evenyao' var str2 = str.reverse() console.log(str2) // 'oayneve olleh'
案例2
代码中并未添加
toString
方法,这个方法是哪里来的?
function People(){ } var p = new People() p.toString()
p.toString()
方法是继承构造函数 Object
的原型对象里定义的 toString
方法,首先 p
会找自己的 toString
方法;如果没有找到,就会沿着__proto__
属性继续到构造函数 People
的 prototype
里找 toString
方法;如果还是没有找到,再继续往 People.prototype
的 __proto__
即 Object.prototype
找 toString
方法,最后找到 toString
方法。