es基础之原型

原型和原型链 #

如何理解js原型?

引用类型: 数组 对象 函数

  • 引用类型都具有对象特性,都可以自由拓展属性,null除外
  • 引用类型都有一个 __proto__属性,值是对象
  • 所有函数都有prototype属性,值是对象
  • 引用类型,__proto__属性值 是 它构造函数的prototype的属性值

__proto__ 是非标准的。是一个对象,指向原型。es6里有了 Object.getPrototypeOf的形式。

注意 Function__proto_===Function.prototype

原型链 #

举例。

function Foo(){}
Foo.prototype.nn=function(){}
var f = new Foo()
f.nnn()
f.toString()

实例中,f本身没有nnn属性,它会到构造函数的prototype中寻找,一层层向上查找,直到找到。再比如都没有定义的.toString() 一直找到 Object 上找到,这就叫原型链。找不到就是 undefined

如何判断 f.nnn 是不是 f自身的属性?hasOwnProperty

var item
for(item in f){
    if(f.hasOwnProperty(item){}
}

for..in 高级浏览器已经屏蔽了原型中的属性,以防万一还是得使用hasOwnProperty

我们通过instanceof可以获得继承的原型,但是不精准。精准的方法,利用原型链:

m.__proto__.constructor 

new 运算符 #

new背后的 技术原理:

var new2 = function(func){
    var o = object.create(func.prototype)
    var k = func.call(o)
    if(typeof k === 'object'){
        return k
    }else{
        return o
    }
}

第一条线,new一个实例。 var f1=new Foo() f1.proto === Foo.prototype Foo.prototype.constructor === function Foo(){} 顺着 Foo继续向上找。Function.prototype, Object.prototype, null

面向对象 #

类和继承

function Animal(){
    this.name = 'name'
}
class Animal2{
    constructor(){
        this.name = 'name'
    }
}
new Animal()
new Animal2()

实现继承 #

组合继承。核心是 Dog.prototype=new Animal()

function Parent(value){this.val = value}
Parent.prototype.getValue=function(){
    console.log(this.val)
}
function Child(value){Parent.call(this, value)}
Child.protype=new Parent()

const child = new Parent()
child.getValue() //1
child instaceof Parent // true

核心。子类构造函数通过call继承了父类属性。然后设置子类原型是父类的实例实现继承

优点。可以传参,传给父类。 缺点,原型继承了父类实例,多了不许需要的属性,浪费。

既然,原型有问题,那就优化掉。

C5.prototype = Object.create(P5.prototype)
C5.prototype.consturctor = C5

断开 prototype ,设定constructor

class #

class只是个语法糖,本质还是函数。 更贴合面向对象的写法,更容易阅读和理解。

class Person{}
typeof Person // 'function'
Person.prototype.constructor === Person
Person instanceof Function

class继承就简单了

class Parent{
    constructor(value){this.val=value}
    getValue(){this.value}
}
class Child extends Parent{
    constructor(value){
        super(value)
        this.value =value
    }
}
let child = new Child(1)
child.getValue //1
child instanceof Parent // true

原型的实际应用 #

jquery,zepto

//定义对象
var zepto = {
  init:function(sel){
    var dom = Array.from(document.qall(selector))
    return zepto.Z(dom,selector)
  }
}
// $(".a") 返回的是dom节点
var $=function(sel){return zepto.init(sel)}
// 构造函数
function Z(dom, selector){
  var i,len=dom?dom.length:0
  for i len i++{this[i]=dom[i]}
  this.length=len
  this.selector=selecto||''
}
zepto.Z=function(dom,selector){return new Z(dom, selector)}
// 定义插件,定义方法
$.fn={
  constructor:zepto.z,
  css:function(){}
}
zepto.Z.prototypo=Z.prototype=$.fn

jquery

jQuery.fn=jQuery.prototype