JS基础--原型和原型链

120 阅读2分钟

构造函数

描述new一个对象的过程

  1. 创建一个新的对象
  2. this 指向这个新对象
  3. 对 this 赋值
  4. 返回 this
// Foo 就是一个构造函数
function Foo(name, age) {
    this.name = name
    this.age = age
    this.class= 'class-1'
    // return this //默认有这一行
}; 
var f = new Foo('zhangsan', 20); // 使用 new 创建了一个实例对象 f
// var f2 = new Foo('lisi', 18); // 可以创建多个对象

构造函数的扩展

  • var a = {} 其实是 var a = new Object()的语法糖
  • var a = [] 其实是 var a = new Arrayt()的语法糖 //推荐 var a={},a=[]这种写法,可读性高,执行效率高
  • function Foo() {...} 其实是 var Foo = new Function(...)
  • 使用instanceof 判断一个函数是否是构造函数

原型规则

  1. 所有的引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性(除了null以外)
  2. 所有的引用类型(数组、对象、函数),都有一个__proto__(隐式原型)属性,属性值是一个普通的对象
  3. 所有的函数,都有一个prototype(显式原型)属性,属性值也是一个普通的对象(对象里面的值是一个构造函数)
  4. 所有的引用类型(数组、对象、函数),都有一个__proto__(隐式原型)属性值指向它的构造函数的prototype属性值
  5. 当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么回去它的__proto__(即它的构造函数的 prototype)中寻找
// 规则1-4示例
var obj = {}
obj.a = 100

var arr = []
arr.a = 100

var fn = function() {}
fn.a = 100

console.log(obj.__proto__) 
console.log(arr.obj.__proto__) 
console.log(fn.obj.__proto__) 

console.log(fn.prototype) 

console.log(obj.__proto__ === Object.prototype) //true

// 规则5示例

//构造函数
function Foo(name, age) {
    this.name = name
}
Foo.prototype.alertName = function() {
    alert(this.name)
}
//创建实例
var f = new Foo('zhangshan')
f.printName = function() {
    console.log(this.name)
}

//测试
f.printName() //'zhangshan'
f.alertName() //'zhangshan'

补充: 循环对象自身的属性

var item
for (item in f) {
  //高级浏览器已经在for in中屏蔽了来自原型的属性
  // 但是这里建议大家还是加上这个判断,保证程序的健壮性
  if (f.hasOwnProperty(item)) {
    console.log(item)
  }
}

原型链

//构造函数
function Foo(name, age) {
    this.name = name
}
Foo.prototype.alertName = function() {
    alert(this.name)
}
//创建实例
var f = new Foo('zhangshan')
f.printName = function() {
    console.log(this.name)
}

//测试
f.printName() //'zhangshan'
f.alertName() //'zhangshan'
// 原型链的示例
f.toString() //要去f.__proto__.proto__中查找
WechatIMG3 1

原型继承的示例:封装一个DOM查询例子

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 {
        return elem.innerHTML
    }
}

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

var app = new Elem('app')
console.log(app.html())
// app.html('<p>hello world</p>')
// app.on('click', function(){
//     alert('clicked')
// })
// 链式操作
app.html('<p>hello world</p>').on('click', function(){
    alert('clicked')
})