Javascript面向对象——创建对象、构造函数的原型
其实:JavaScript中的创建类,就是创建一个构造函数,在创建对象时用到new这个关键字,
一、创建对象
1.函数创建对象
function creatObj(name,age){ //手动创建一个对象 var obj={} //为对象添加属性 obj.name=name obj.age=age obj.sayHi=function(){ console.log("hello world!") } //返回对象 return obj } //调用方法创建不同对象 var obj1=creatObj("小明",18) var obj2=creatObj("小花",20)
2.自定义构造函数创建对象
构造函数使用
1、构造函数和普通函数没有区别,只是在调用是和new一起使用
2、书写构造函数时,函数首字母大写
=>当看到首字母大写时就知道要用new关节字去调用
3、调用时要用new关键字
=>如果没有就不会自动创建对象、不会自动返回对象,也不能用this
function CreatObj(name,age){ //构造函数首字母大写 //自动创建一个对象 //为对象添加属性 this.name=name //this代表了指向调用的对象 this.age=age this.什么=什么 this.obj.sayHi=function(){ console.log("hello world!") } //自动返回对象 } //调用方法创建不同对象 var obj1=new creatObj("小明",18) //加了一个new var obj2=new creatObj("小花",20)
二、构造函数的原型(prototype)
定义:每一个函数天生自带的属性,叫做prototype,是一个对象
=>既然prototype是一个对象,我们就可以使用操作对象的语法,向里面添加内容
作用:当函数里面没有想调用的属性或方法时,就会去函数的原型里面去找。
不合理性:如果把方法直接写在函数体里面时(如上一个例子所示),每创建一个对象时都会从新创建一个方法。(造成资源浪费)
解决办法:使用函数原型,如果把方法放在原型里面后,不同对象创建的方法都是同一个方法。
//格式:构造函数.prototype.方法名=function(){ } //为Creatobj的原型添加方法 Creatobj.prototype.sayHi=function(){ consle.log("hello world!") } function Creatobj(name,age){ //构造函数首字母大写 //自动创建一个对象 //为对象添加属性 this.name=name //this代表了指向调用的对象 this.age=age this.什么=什么 //自动返回对象 } //调用方法创建不同对象 var obj1=new creatObj("小明",18) //加了一个new var obj2=new creatObj("小花",20) //调用Creatobj里原型的方法 obj1.sayHi() //可以正常调用
1.对象自带的方法(__proto__)
概念:每个对象天生自带属性__proto__,指向构造函数是prototype,当访问对象成员时先在自己身上找不到再去找__proto__
//构造函数 function Person(){ } //给Person的原型赋值 Person.prototype.a=100 Person.prototype.say=function(){ console.log("hello") } //创建两个对象 var p1=new Person() var p2=new Person() //判断对象的里 console.log(p1.__proto__===Person.prototype) console.log(p2.__proto__===Person.prototype) //结果都为true, //说明所有对象使用同一个原型
2.原型链
原型链概念:
1、用__proto__ 串联起来的对象链状结构
2、每一个对象类型都有一个属于自己的原型链
3、作用:为了访问对象成员
访问机制
当你需要访问对象的成员的时候
首先在自己身上查找,如果有直接使用
如果没有,会自动去__proto__ 上查找
如果还没有,会再去__proto__ 上查找
直到objiect.prototype都没有,那么返回undefined
//构造函数 function Person(){ } //给Person的原型赋值 Person.prototype.a=100 Person.prototype.say=function(){ console.log("hello") } //创建两个对象 var p1=new Person() var p2=new Person()
看上面代码回答问题
问题1:实例对象的 __proto__ 指向谁?
=>指向所属构造函数的原型prototype
=>p1 所属的构造函数是Person
=>p1. __proto__ 指向Person的prototype
问题2:Person.prototype的 __proto__ 指向谁?
=>Person.prototype所属的构造函数是谁?
=>Person.prototype是个对象数据类型(Object)
=>在JS里所有的Object数据类型都是属于Object这个内置构造函数的
=>Person.prototype的 __proto__ 指向Object.prototype
问题3:Person的 __proto__ 指向谁的?
=>Person是个函数,函数本身就是一个对象,就会有 __proto__
=>在JS里所有的函数都是属于Function这个内置构造函数的实例
=>Person. __proto__的 指向Function.prototype
问题4:Objiect.prototype的 __proto__ 指向谁的?
=>Objiect.prototype是个对象数据类型,所有的对象都是属于Object这个内置构造函数的。
=>注意:Objiect.prototype在JS中是顶级原型,是没有 __proto__
=>Objiect.prototype的 __proto__ 指向null
问题5:Objiect的 __proto__ 指向谁的?
=>Objiect是个内置构造函数,同时是一个函数,也是一个对象
=>在JS里所有的函数都是属于Function这个内置构造函数的实例
=>Objiect的 __proto__ 指向Function.prototype
问题6:Function.prototype的 __proto__ 指向谁的?
=>Function.prototype是对象数据类型
=>在JS里所有的对象都是属于Object这个内置构造函数的实例
=>Function.prototype的 __proto__ 指向Object.prototype
问题7:Function的 __proto__ 指向谁的?
=>Function是个内置构造函数,同时是一个函数,也是一个对象
=>在JS里所有的函数都是属于Function这个内置构造函数的实例
=>Fanction 自己是自己的构造函数
=>Fanction 自己是自己的实例对象
=>Function的 __proto__ 指向Function