JS构造函数,原型链,原型对象总结

479 阅读3分钟

JS构造函数,原型链,原型对象总结

构造函数

构造函数第一个字母大写

使用this指向当前对象的 公有属性

var Car = function(wheels, seats, engines) {
  this.wheels = wheels;
  this.seats = seats;
  this.engines = engines;
};
var myCar = new Car(6,3,1)

也可以创建私有属性私有方法,它们两个在对象外部是不可访问的

用var 关键词去创建变量,代替this创建私有属性;比如,我们想记录我们的car行驶的 speed ,但是我们希望外面的代码对 speed 的修改只能是加速或减速(而不是变成字符串、直接赋值成某个速度等其他操作),那么如何达到这类操作的目的呢?

var Car = function() {
    // this is a private variable
    var speed = 10;
    // these are public methods
    this.accelerate = function(change){
        speed =+ change
    }
    this.decelerate = function() {
    	speed -= 5;
   }
    this.getSpeed = function(){
        return speed
    }
}

instanceof

判断某个对象是否为某个构造函数的实例

console.log(myCar instanceof Car)

静态成员和实例成员

静态成员: 写成对象字面量的形式,直接使用对象来调用。

// 一般用于 工具  的写法,工具中使用静态成员,即工具中的方法如 max(),PI 只有一个
var MyMath = {
    PI:3.1415,
    max:function(){},
    min:function(){}
}

MyMath.PI
MyMath.max()

实例成员:构造函数中的成员: p.sayHi()

function Person(name,age) {
    this.name = name,
    this.age = age,
    this.sayHi = function(){}
}
//当有很多实例的时候,使用构造函数来创建
var p = new Person('zs',18)

构造函数原型

每一个构造函数都有一个属性 : 原型/原型对象 prototype

function Person(name,age) {
    this.name = name,
    this.age = age,
}
console.dir(Person.prototype)
//那么就可以为Person的原型对象增加方法,这样用Person构造函数创建出来的实例都可以访问新增加的方法
Person.prototype.sayHi = function() {
    console.log("hi")
}

 var p1 = new Person('ls',12)
 var p2 = new Person('tom',13)
 
 p1.sayHi()
 p2.sayHi()
 
 这样做的优点: 节省内存

 p1.sayHi 和  p2.sayHi 是相等的,指向同一个内存空间
 如果在Person()内部定义 sayHi 方法的话,新创建的p1,p2会各自在内存创建空间
 对象本身有 __proto__ 属性,当调用对象的属性或方法时,先去找对象本身的属性/方法;找不到的话 再去调原型中的属性/方法
 
 对象的__proto__ 属性 等于 构造函数的prototype,对象可以访问原型对象所有成员
 
 p1.__proto__ === Person.prototype
 > true
 
 constructor 记录了创建该对象的构造函数
 p1.constructor === Person
 > true

注意:constructor 属性
function Person(){
    
}
var p1 = new Person()
console.log(p1.constructor === Person.prototype.constructor)
>true

原因:
当获取 person.constructor 时,其实 person 中并没有 constructor 属性,当不能读取到constructor 属性时,会沿着原型链从 person 的原型也就是 Person.prototype 中读取,正好原型中有该属性,所以:

person.constructor === Person.prototype.constructor

原型链

同理如图:

查找对象是否具有某个方法或属性时,会由底向上查找:当底层对象没有时,会在其原型对象上找,其原型对象没用时,会再其原型对象的原型对象上找;

使用原型对象注意点

  1. 当我们改变构造函数的prototype的时候,需要重新设置constructor属性
//在Person.prototype.sayHi = function(){} 基础上进一步改进
Person.prototype = {
    constructor:Person,     //注意点
    sayHi:function(){
        console.log("hi")
    }
}

var p1 = new Person('zs',18)
p1.sayHi()
  1. 先设置原型属性,再创建对象,才能访问原型对象的成员

原型对象的应用

拓展内置对象的功能,比如给array方法 增加一个求偶数的和的功能

var arr = [1,2,4,5]
Array.prototype.getSum = function(){
    var sum = 0;
    for (var i = 0;i < this.length; i++){
        if(this[i] %2 === 0) {
            sum += this[i]
        }
    }
    return sum
}
//但是能不能用下面这种方法呢?
Array.prototype = {
    getSum = function(){}
}
//答案是不能!因为Array,String 都属于内置对象,如果用以上方法,会覆盖掉他们本身的那些方法