原型链与继承
作用域、原型链、继承与闭包详解 注意:本章讲的是在es6之前的原型链与继承。es6引入了类的概念,只是在写法上有所不同,原理是一样的。 几个面试常问的几个问题,你是否知道
instanceof的原理
如何准确判断变量的类型
如何写一个原型链继承的例子
描述new一个对象的过程
也许有些同学知道这几个问题的答案,就会觉得很小儿科,如果你还不知道这几个问题的答案或者背后所涉及到的知识点,那就好好看完下文,想必对你会有帮助。先不说答案,下面先分析一下涉及到的知识点。 什么是构造函数JavaScript没有类的概念,JavaScript是一种基于对象的语言,除了五中值类型(number boolean string null undefined)之外,其他的三种引用类型(object、Array、Function)本质上都是对象,而构造函数其实也是普通的函数,只是可以使用构造函数来实例化对象。
事实上,当任意一个普通函数用于创建一类对象时,它就被称作构造函数。像js的内置函数Object、Array、Date等都是构造函数。在定义构造函数有以下几个特点:
以大写字母开头定义构造函数
在函数内部对新对象(this)的属性进行设置
返回值必须是this,或者其它非对象类型的值
下面定义一个简单的、标准的构造函数:
function Obj(){ this.name = ‘name‘ return this // 默认有这一行 } var foo = new Obj() // 使用上面定义的构造函数创建一个对象实例 原型特性js原型有5个特点,记住这5条特点,相信你一定会弄明白长期困扰你的原型关系。
除了null所有引用类型(Object、Array、Function)都有对象特性,也就是都可以自由扩展属性。
所有引用类型都有一个_proto_属性(又称为:隐式属性),_proto_是一个普通的对象。所有的对象都会有一个constructor属性,constructor始终指向创建当前对象的构造函数
所有的函数都有一个prototype属性(又称为:显式属性),也是一个普通对象,这个prototype有一个constructor属性指向该函数。
所有的引用类型的_proto_属性指向它的构造函数的prototype属性(比如:obj._proto_指向Object.prototype,obj是定义的一个普通对象,Object是js的内置函数)
当从一个对象中获得某个属性时,如果这个对象没有该属性,就会去它的_proto_(也就是它的构造函数的prototype)中去寻找
先来解释一下这几条:
第一条的自由扩展性可以通过一个简单的例子来看
第二条和第三条是javascript就是这么规定的,没什么好说的
第四条可以这么理解,当定义一个引用类型的变量var obj = {} 其实是var obj = new Object()的语法糖,这样Object就是obj的构造函数,根据第4条规定,obj._proto_ === Object.prototype,如果不理解可以看看上一章我们讲的js内置函数和上面讲的构造函数
第五条应该好理解,当从obj中获取某个属性时,如果obj中没有定义该属性,就会逐级去它的_proto_对象中去寻找,而它的_proto_指向Object的prototype,也就是从Object的prototype对象中去寻找。
原型链与继承 如果上面明白了原型,那么原型链就会很好理解根据原型定义的第4条和第5条,很容易发现通过对象的_proto_和函数的prototype把我们变量和构造函数(自定义的构造函数以及内置构造函数)像链子一样链接起来,所以又叫他原型链。
有了原型链,就有了继承,继承就是一个对象像继承遗产一样继承从它的构造函数中获得一些属性的访问权。从下面一个小例子理解:
function Animal (name) { // 属性 this.name = name || ‘Animal‘; // 实例方法 this.sleep = function(){ console.log(this.name + ‘正在睡觉!‘); } } // 原型方法 Animal.prototype.eat = function(food) { console.log(this.name + ‘正在吃:‘ + food); }; // 原型继承 function Cat(){ } Cat.prototype = new Animal(); Cat.prototype.name = ‘cat‘;上面例子中在Foo构造函数的prototype中自定义一个somefn函数。然后通过new Foo()创建一个对象实例并赋值给bar变量,此时bar就等于{name:‘bar‘}。然后bar.somefn就去bar对象中寻找somefn这个属性,发现找不到,然后就去它的_proto_(其实就是Foo的prototype)中寻找,发现somefn就在Foo的prototype中定义了,就可以愉快的调用并执行somefn了。
这里其实就是一个原型链与继承的典型例子,开发中可能构造函数复杂一点,属性定义的多一些,但是原理都是一样的。
留一个问题,根据上面例子,如果执行bar.stString(),应该去哪里找toString这个方法? (提示:prototype也是普通对象,也有自己的_proto_) 几种继承方式这几种都是es5中的继承,es6中提供了class类,继承起来更方便。
原型继承温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/web/40515.html
- 上一篇:jTopo HTML5 Canvas 画图组件
- 下一篇:css的响应式布局和动画