原型和原型链

原型链

原型五大规则

  1. 所有的引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性。
// object
var obj = {}
obj.a = 100     // 100

// array
var arr = []
arr.a = 100     // 100

// function
function fn() {}
fn.a = 100      // 100
  1. 所有的引用类型(数组、对象、函数),都有一个__proto__属性,属性值是一个普通的对象。
// object
var obj = {}
console.log(obj.__proto__)   // { constructor: ƒ, __defineGette...

// array
var arr = []
console.log(arr.__proto__)   // { constructor: ƒ, __defineGette...

// function
function fn() {}
console.log(fn.__proto__)    // { constructor: ƒ, __defineGette... 
  1. 所有的函数(函数),都有一个prototype(显式原型)属性,属性值也是一个普通的对象
// object
var a = {}
console.log(a.prototype)     // undefined
// function
function fn() {}
console.log(fn.prototype)    // { constructor: ƒ }
  1. 所有的引用类型(数组、对象、函数),proto属性值指向它的构造函数的prototype属性值
var obj = {}
console.log(obj.__proto__ === Object.prototype)   // true
// Object 是内置构造函数
  1. 当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的proto(即它的构造函数的prototype)中寻找。
// 构造函数(规范命名,首字母大写)
function Foo(name, age) {
    this.name = name
    this.age = age
    ...
    // return this   // 默认返回
}

Foo.prototype.alertName = function() {
    console.log(this.name, 'prototype')
}

// 创建实例
var f = new Foo('zhangsan', 12)
f.printName = function() {
    console.log(this.name, '__proto__') 
}

f.printName()           // 'zhangsan', '__proto__'   f自身有这个属性
f.alertName()           // 'zhangsan', 'prototype'   f没有这个属性,它的构造函数Foo的prototype有
f.consoleName()         // undefined                 f、Foo都没有
f.name.toUpperCase()    // 'ZHANGSAN'                f.__proto__.__proto__

原型链继承

先讨论new一个对象的过程

function Foo(name, age) {
    this.name = name
    this.age = age
    
    // return this 默认有这一行
}
var f = new Foo('zhangsan', 12)

// 四个过程
// 1.创建一个空对象
var obj = new Object()
// 2.让Foo中的this指向obj, 并执行Foo的函数体
var result = Foo.call(obj)
// 3.设置原型链,将obj的__proto__成员指向了Foo函数对象的prototype成员对象
obj.__proto__ = Foo.prototype
// 4.判断Foo的返回值类型,如果是值类型,返回obj;如果是引用类型,返回这个引用类型的对象。
if (typeof result === 'object') {
    f = result
} else {
    f = obj
}

实现一个原型继承的实例

// 构造函数
function Elem(id) {
    this.elem = document.getElementById(id)
}

Elem.prototype.html = function (val) {
    var elem = this.elem
    if (val) {
        elem.innerHTML = val 
        return this //链式操作
    } else {
        retrun elem.innerHTML
    }
}

Elem.prototype.on = function (type, fn) {
    var elem = this.elem
    elem.addEventListener(type, fn)
}


// 
123
var div1 = new Elem('div1') // html console.log(div1.html()) // 123 div1.html('aaa') //
aaa
// on div1.on('click', function(){ console.log('this is click') })

你可能感兴趣的:(原型和原型链)