摘要:之二关于原型开篇我记得初学时,最难懂的概念就是的原型,而且这个概念在笔试面试中常常提到,因此今天我们把这个概念拿出来,好好聊一聊。
之二:关于js原型 1. 开篇
我记得初学js时,最难懂的概念就是js的原型,而且这个概念在笔试面试中常常提到,
因此今天我们把这个概念拿出来,好好聊一聊。
在仔细讲解之前,我们先来看一道题,这道题来自JavaScript高级程序设计中原型链那一节:
function SuperType(){ this.property = true; } SuperType.prototype.getSuperValue = function(){ return this.property; }; function SubType(){ this.subproperty = false; } SubType.prototype = new SuperType(); SubType.prototype.getSubValue = function (){ return this.subproperty; }; var instance = new SubType(); alert(instance.getSuperValue());
请大家猜一猜最后alert出的结果是什么?
大家先思考一下再看下面的内容。
2. 几个知识点如果上面的题没解出来,也不要灰心丧气,因为有可能有的人解出来的结果也不一定对。
要想弄明白原型等一系列概念,其实只需要记住这几个知识点。
_proto_:任何一个对象Object都有_proto_,它是每一个对象的私有属性,是天生自带的。
prototype:不是任何对象都有prototype,只有构造函数有prototype,是后天赋予的。
其实只需要记住一句话:调用一个对象的属性或方法,一但这个对象中没有,就去这个对象的_proto_中查找。这个对象的_proto_指向自己构造函数的prototype属性
然后我们来看一张图:
再来看一个例子:
var Person = function () { this.sleep = "Zzzzz..." } Person.prototype.sayHello = function () { console.log("hello world"); } var zhangsan = new Person(); zhangsan.sayHello();
其实zhangsan这个对象下面只有一个sleep属性,是没有sayHello方法的。
但是通过原型链查找会查zhangsan._proto_也就是查找它的构造函数的Person.prototype,Person.prototype下有sayHello这个方法,所以会在控制台输出hello world
所以啦,万变不离其宗!
除了最新的ES6外,js其实是没有继承和类的概念的,因此想要达到js的继承就要通过模拟的方式。
这里将主要介绍三种继承的方式:纯原型链继承,借用构造函数继承,组合继承
多说无益,来个简单暴力直接的方式,直接上代码:
function Father() { this.likeFood= ["牛排","饺子","啤酒","可乐"] } Father.prototype.saylikeFood = function () { console.log(this.likeFood); }; function Son() { } Son.prototype = new Father(); var zhangsan = new Son(); zhangsan.likeFood.push("西瓜"); zhangsan.saylikeFood(); // ["牛排", "饺子", "啤酒", "可乐", "西瓜"]
Ok,这就是纯原型链的继承方式,其实说白了就是把继承的对象的prototype等于继承自构造函数的实例。
但是这样的方式有问题。接着上面的代码的后面我们再写:
var lisi = new Son(); lisi.saylikeFood(); // ["牛排", "饺子", "啤酒", "可乐", "西瓜"]
看出问题了吧,zhangsan直接修改了其构造函数的likeFood,
导致我们再实例的对象也收到了修改的影响,
因此这种继承方式有缺陷
还是多说无益,我们直接来看例子,上代码:
function Father(name) { this.name = name; this.sayName = function () { console.log(this.name); } } function Son(name, age) { Father.call(this, name); this.age = age; } var zhangsan = new Son("zhangsan", 17);
这种继承方式并没有利用到原型以及原型链的概念,它主要利用call的特性,call的第一个参数传入this,后面的参数传入函数所需的参数。
这种方式归根结底其实就是在实例一个对象的时候,向这个对象的上面添加所需的属性和方法。
不信的话可以输出zhangsan看一下
但是其实这种方式也有问题,什么问题呢?
按照这种方式,每次new一个对象,就是实例化一个对象,都会向这个对象身上添加一堆属性和方法。
添加属性是没问题的,但是每次在对象身上添加的方法,这个函数就要重写一次。
函数不能进行复用,这就是最大的问题!
这次要多说两句,组合继承其实分别是拥有以上两种方法的优点,同时也规避了以上两种方法的缺点。
这种方法的应用是最广泛的,是最普遍的,举个栗子来看一下:
function Father(name) { this.name = name; } Farther.prototype.sayName = function () { console.log(this.name); } function Son(name, age) { Farther.call(this, name); this.age = age; } Son.prototype = new Father(); Son.constructor = Son; Son.prototype.sayage = function () { console.log(this.age); } var zhangsan = new Son();
来看一下,这种方式不错吧!
其实除了组合继承外,还有两种继承方式:原型式继承和寄生式继承,
这两种方式感兴趣的同学可以自行了解一下
抱歉,这篇这么迟才出来,其实应该早早完事的。
我最近买了一本《学习JavaScript数据结构与算法》再看,我准备新开辟一个专栏来写一下我的学习笔记。
下一次我决定和大家讲讲闭包的事。
本期的内容是原创的,但其实主要是看了《JavaScript高级程序设计》的启发!
建议你也去看书,读一下这本书的第六章的继承那一部分,相信你也会深有启发。
加油!
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/87875.html
摘要:避免脆弱的基类问题。红牌警告没有提到上述任何问题。单向数据流意味着模型是单一的事实来源。单向数据流是确定性的,而双向绑定可能导致更难以遵循和理解的副作用。原文地址 1. 你能说出两种对 JavaScript 应用开发者而言的编程范式吗? 希望听到: 2. 什么是函数编程? 希望听到: 3. 类继承和原型继承的不同? 希望听到 4. 函数式编程和面向对象编程的优缺点? ...
摘要:所支持的面向对象编程包括原型继承。发明于年的就是首批支持函数式编程的语言之一,而演算则可以说是孕育了这门语言。即使在今天,这个家族的编程语言应用范围依然很广。 1. 能说出来两种对于 JavaScript 工程师很重要的编程范式么? JavaScript 是一门多范式(multi-paradigm)的编程语言,它既支持命令式(imperative)/面向过程(procedural)编程...
摘要:所支持的面向对象编程包括原型继承。发明于年的就是首批支持函数式编程的语言之一,而演算则可以说是孕育了这门语言。即使在今天,这个家族的编程语言应用范围依然很广。 1. 能说出来两种对于 JavaScript 工程师很重要的编程范式么? JavaScript 是一门多范式(multi-paradigm)的编程语言,它既支持命令式(imperative)/面向过程(procedural)编程...
摘要:所支持的面向对象编程包括原型继承。发明于年的就是首批支持函数式编程的语言之一,而演算则可以说是孕育了这门语言。即使在今天,这个家族的编程语言应用范围依然很广。 1. 能说出来两种对于 JavaScript 工程师很重要的编程范式么? JavaScript 是一门多范式(multi-paradigm)的编程语言,它既支持命令式(imperative)/面向过程(procedural)编程...
阅读 1597·2021-11-04 16:11
阅读 3308·2021-09-09 11:33
阅读 1558·2019-08-30 15:54
阅读 619·2019-08-30 15:44
阅读 3173·2019-08-30 15:43
阅读 2553·2019-08-30 13:06
阅读 1697·2019-08-29 17:00
阅读 894·2019-08-29 15:33