es基础之原型

原型和原型链

如何理解js原型?

引用类型: 数组 对象 函数

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

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

注意 Function__proto__===Function.prototype

原型链

举例。

1
2
3
4
5
function Foo(){}
Foo.prototype.nn=function(){}
var f = new Foo()
f.nnn()
f.toString()

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

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

1
2
3
4
var item
for(item in f){
if(f.hasOwnProperty(item){}
}

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

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

1
m.__proto__.constructor

new 运算符

new背后的 技术原理:

1
2
3
4
5
6
7
8
9
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

面向对象

类和继承

1
2
3
4
5
6
7
8
9
10
function Animal(){
this.name = 'name'
}
class Animal2{
constructor(){
this.name = 'name'
}
}
new Animal()
new Animal2()

实现继承

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

1
2
3
4
5
6
7
8
9
10
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继承了父类属性。然后设置子类原型是父类的实例实现继承

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

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

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

断开 prototype ,设定constructor

class

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

1
2
3
4
class Person{}
typeof Person // 'function'
Person.prototype.constructor === Person
Person instanceof Function

class继承就简单了

1
2
3
4
5
6
7
8
9
10
11
12
13
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//定义对象
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=selector||''
}
zepto.Z=function(dom,selector){return new Z(dom, selector)}
// 定义插件,定义方法
$.fn={
constructor:zepto.z,
css:function(){}
}
zepto.Z.prototype=Z.prototype=$.fn

jquery

1
jQuery.fn=jQuery.prototype

请我喝杯咖啡吧~