一.编程思想
面向过程编程:
- 优点:性能比面向对象高
- 缺点:没有面向对象易维护、易复用、易扩展
面对对象编程:
- 优点:易维护、易复用、易扩展,由于面向对象有封装 、继承、多态性的特性,可以设计出低耦合的系统,使 系统 更加灵活、更加易于维护
- 缺点:性能比面向过程低
二.原型
原型:
- 原型是一个对象,称为 prototype 为原型对象
- 原型的作用:1.共享方法 2.可以把那些不变的方法,直接定义在 prototype 对象上
- 构造函数和原型里面的this指向实例化对象
constructor属性:
该属性指向原型对象的构造函数(创建构造原型的构造函数)
对象原型:
对象原型身上有一个属性 constuctor,指向当前原型对象的构造函数
(构造函数的身上prototype等于构造函数的原型对象,
构造函数的原型对象的constructor等于构造函数本身)
function Person(uname, age) {
this.uname = uname,
this.age = age
}
// 实例化出一个对象
const p1 = new Person('张三', 18)
// 给构造函数本身添加 方法
Person.prototype.dance = function () {
console.log('跳舞')
}
p1.dance()
// 有一个__proto__属性值指向构造函数的原型对象进行访问原型对象身上的方法
console.log(p1.dance.__proto__ === p1.prototype)
call(对象方法:可以改变this指向)
// call()可以改变函数里面的this指向 函数名.call(对象)
// 函数名.call(对象,函数里面的参数,函数里面的参数)
// 通过var 声明的全局变量 相当于给window对象添加 属性
// 函数 相当于 给window对象添加的方法
function f(x,y,z) {
console.log(this,x,y,z)
}
const obj = {
uname: '张三'
}
f.call(obj,10,20,30)
原型继承:
借用父结构函数实行继承属性:
子构造函数借用父构造函数,将父函数变成普通函数调用
原型继承继承方法:
子构造函数.prototype=父构造函数.prototype(相互引用)
子继承父构造函数方法:
prototype=new 父构造函数
// 子构造函数继承父构造函数的属性
function Father(uname, age) {
this.uname = uname,
this.age = age
}
Father.prototype.sayHi = function () {
console.log('说哈喽')
}
// 借用 父构造函数 将Father 函数当成普通函数 调用
function Son(uname, age, gender) {
Father.call(this, uname, age)
this.gender = gender
}
Father.prototype.sss = function () {
console.log('111111');
}
const p2 = new Father('张三', 20)
// 相互继承
Son.prototype = Father.prototype
// 继承父构造函数的方法
// Son.prototype = new Father()
const son1 = new Son('周杰伦', 20, '男')
// console.log(son1)
// son1.sayHi()
// son1.sss()
console.dir(son1)
console.dir(p2)
原型链作用:
作用:成员的访问规则
理解:在JavaScript中,原型也是一个对象,通过原型可以实现对象的属性继承,在JavaScript的 函数对象中包含了一个prototypr内部属性,这个属性所对应的就是该函数对象的原型,prototype作为函数对象的内部属性,是不能直接被访问的,所以为了方便查看一个对象的原型,Firefox和Chrome内核的Javascript引擎中提供了 proto这个非标准的访问器,主要作用是为了实现继承与扩展对象
原型链:
当访问一个对象的属性和方法时,会先在这个对象本身属性上查找,如果没有就去它的__proto__原型上查找,就是它的构造函数prototype,如果还没有找到就会在构造函数的prototype的__proto__中查找,一层一层的向上查找
function Star() {
}
console.dir(Object)
const ldh = new Star()
// 实例化对象的__proto__指向 当前的构造函数本身
// 实例化对象的__proto__的__proto__
// console.log(ldh.__proto__===Star.prototype)
// console.log(ldh.__proto__.__protot__===Object.prototype)
// console.log(ldh.__proto__.proto__.__proto__)
// 原型链的作用:成员的访问规则
// 实例化对象.方法()先看看当前实例化对象里面有没有该成员 如果有就调用方法
// 如果没有 构造函数的原型对象身上查找是否有该方法 如果有就调用
instanceof运算符用于检测实例化对象是否属于当前的构造函数
// instanceof 运算符用于检测实例化对象是否属于当前的构造函数
function Father() { }
function Son() { }
const f = new Father()
const s = new Son()
console.log(f instanceof Father) //true
console.log(s instanceof Father) //false