2017-12-27

原型和原型链

示例

  • 如何准确判断一个变量是数组类型
  • 写一个原型链继承的例子
  • 描述 new 一个对象的过程
  • zepto(或其他框架)源码中如何使用原型链

知识点

  • 构造函数
  • 构造函数的扩展
  • 原型规则和示例
  • 原型链
  • instanceof

构造函数{#t1}

function Foo (name, age) {
  this.name = name
  this.age = age
  this.class = 'class-1'
  // return this // 默认有这一行
}

var f = new Foo('zhangsan', 20) // new的时候,this变成一个空对象
// var f1 = new Foo('lisi', 21) // 创建多个对象

构造函数的扩展{#t2}

所有引用类型都有构造函数

  • var a = {}var a = new Object()的语法糖
  • var a = []var a = new Array()的语法糖
  • function Foo(){...}var Foo = new Function(...)的语法糖
  • 使用instanceof判断一个函数是否是一个变量的构造函数arr instanceof Array

原型链规则和示例

原型规则是原型链的基础

  • 所有的引用类型(数组、对象、函数),都具有对象特性,即可以自由扩展属性(除了null以外)
var obj = {}
obj.a = 100
var arr = []
arr.a = 100
function fn() {...}
fn.a = 100
  • 所有的引用类型(数组、对象、函数,null除外),都有__proto__(隐式原型)属性,属性值是一个普通的对象
console.log(obj.__proto__)
console.log(arr.__proto__)
console.log(fn.__proto__)
  • 所有的函数,都有一个prototype(显式原型)属性,属性值也是一个普通对象
console.log(fn.prototype)
  • 所有的引用类型(数组、对象、函数),__proto__属性指向其构造函数的prototype属性值
console.log(obj.__proto === Object.prototype)
  • 当试图得到一个引用类型(对象、数组、函数)的某个属性时,如果这个引用类型(对象、数组、函数)本身没有这个属性,那会去其__proto__(其构造函数的prototype中寻找

自身的属性

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('zhangsan')
f.printName = function () {
  console.log(this.name)
}

// 测试
f.printName()
f.alertName()
f.toString() // 要从f.__proto__.__proto__ 中查找
2017-12-27_第1张图片
微信图片_20171226160104.png

instanceof

用于判断引用类型对象属于哪个构造函数的方法

f instanceof Foo 的判断逻辑是:
f 的__proto__一层一层往上,能够对应到Foo.prototype
f instanceof Object也是f 的__proto__一层一层往上,能够对应到Object.prototype

实例

  1. 写一个原型链继承的例子
// 动物示例
function Animal () {
  this.eat = function () {
    console.log('Animal eat')
  }
}
// 狗
function Dog () {
  this.bark = function () {
    console.log('Dog bark')
  }
}

Dog.prototype = new Animal()
// 哈士奇
var hashiqi = new Dog()
hashiqi.bark()
hashiqi.eat()
// 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)
  return this
}

var div1 = new Elem('id')
div1.html('

Javascript start

').on('click', function () { alert('click') }).html('

Javascript end

')
  1. 描述new 一个对象的过程
// 构造函数
function Foo (name, age) {
  this.name = name
  this.age = age
  this.class = 'class-1'
  // return this // 默认有这一行
}

var f = new Foo('zhangsan', 20) // new的时候,this变成一个空对象
  • 创建一个新对象
  • this指向这个新对象
  • 执行代码,即对this赋值
  • 返回this

你可能感兴趣的:(2017-12-27)