对象原型
原型:任何对象天生都自带一个属性:__proto__ - 对应的值,也是一个对象 - 原型 / 原型对象
var obj = { name: '张三' } // console.log(obj); // console.log( 111, obj.__proto__ ); obj.__proto__.name = '李四' console.log(obj.name); // 自己的name console.log(obj);
原型的作用:对象就天生就能使用自带的原型中的属性和方法。当对象使用一个属性或方法的时候,先在自己对象上只要这个属性或方法,如果自己有,就使用自己的属性或方法,如果自己没有,才会去原型上找属性和方法
只要是对象,天生自带原型 - 对象.__proto__ 原型上的属性和方法天生就能被对象使用,先在自己上找,自己没有就找原型的
函数的原型
任何函数当做对象去看待的时候,他也天生自带一个属性 prototype 对应的值也是一个对象 - 对象 - 原型 / 原型对象
function Person() { } var p = new Person() console.log(p); var p1 = new Person() console.log(p1); console.log(p.__proto__); console.log(p1.__proto__); console.log(p.__proto__ === p1.__proto__); // true
构造函数的原型 === new出来的对象的原型
被一个构造函数new出来的所有对象的原型都是同一个
一个构造函数可以new出来无数个对象,他们的原型都是同一个
构造函数理解为母亲,将原型理解为父,将new出来的对象理解为子
原型解决全局方法被覆盖的问题
原型 = 构造函数.prototype = new出来的对象.__proto__
将方法放在原型上,原型是一个局部,能被new出来的多个对象共用
function Person(name, age) { this.name = name this.age = age } Person.prototype.eat = function() { console.log(this.name + '在吃饭'); } // 定义在全局中的变量容易被覆盖 var p1 = new Person('张三', 12) var p2 = new Person('李四', 13) console.log(p1.eat === p2.eat); // true console.log(p1, p2); p1.eat() p2.eat()
当我们使用面向对象的方式操作对象的话,使用自定义构造函数创建对象并给对象添加属性,将对象方法添加到原型上
构造器
任何原型天生自带属性叫 constructor 的值,是一个函数,指的是对应的函数 - 构造器
function Person() { this.name = '张三' } // console.log(Person.prototype); var obj = { age: 45, constructor: Person } Person.prototype = obj var p = new Person() console.log(p.age); console.log(Person.prototype);
原型链
function Person() { } var p = new Person() console.log(p); console.log( p.__proto__.__proto__.__proto__ ); // null var a = new Number(10) console.log(a); var body = document.querySelector('body'); console.dir(body) body.addEventListener()
当我们去访问一个对象中的属性时,首先先在自己上面找这个属性是否存在,如果存在了,访问成功,自己没有的话,就去原型找,原型有的话,访问到的是原型上的属性,原型上不存在,找原型的原型 。。。。 直到null,就返回undefined