第九课:js的类与继承
因为本书是js的框架设计,因此观看本书的必须有js基础,看不懂,请不要觉得自己差。我也是看了5遍js高级程序设计,才能看懂这本书的。
有关js的构造函数,继承的方法大家可以去看js的高级程序设计,我这里只讲一个大家比较容易弄错的问题:
function A(){}
A.prototype = { aa:1 }
var a = new A();
A.prototype = { aa:2 }
console.log( a.aa )
大家会认为,会打印出2.因为构造函数A的原型改变了,当访问实例对象时,如果实例对象没有的属性,就去访问它的原型属性,所以应该是2.
但是结果却是1.为什么会这样呢?
大家要看下在改变A.prototype时,a实例已经new出来了。所以就不能按正常的方式来理解了(如果new出来的实例是在改变A原型之后,那么肯定就是2了。)
其实每当我们new出一个对象的时候,js都会默认设置这个对象一个内部属性[[Prototype]](现在的浏览器可以通过实例对象的_proto_属性访问),它指向的是new时的原型对象。
因此,a._proto_指向的是{ aa:1 } ,当你在new它后面改变A.prototype = { aa:2 },不会对a的_proto_属性有任何影响,因此打印出来的是1.之后,如果你再new A方法,那么,打印出来的aa就是2了。
还有一个比较重要的问题:
大家可以去打印一下a.constructor,打印出来的是Object,为什么不是A呢?
问题就出在这里:A.prototype = { aa:1 }。当你新建一个A构造方法的时候,js会默认生成A.prototype对象(对象有一个constructor属性指向A)。但是你在它下面马上改变了它的原型:A.prototype = { aa:1 }。这时,A.prototype对象的constructor会默认为Object。所以,你必须A.prototype = { aa:1, constructor:A },把constructor的指向恢复为A。 (大家要区分下这两种方式:A.prototype = { aa:1 },A.prototype.aa =1.第一种方式,是重新定义A.prototype对象,会覆盖之前对A.prototype对象的赋值。第二种方式,是添加属性,不会覆盖之前的定义,因此也不会改变constructor的指向)
面试官经常会问的问题:new操作发生了什么事?
(1)创建一个空对象instance。(2)instance._proto_ = instanceClass.prototype。(3)将构造函数里面的this=instance。(4)执行构造函数里面的代码。(5)判定有没有返回值,没有返回值默认为undefined。最后判断返回值的类型,如果为复合数据类型(数组,函数,对象,正则对象,日期对象),则直接返回,如果不是就返回this(instance)。
一些继承库里面的不常见方法和技巧介绍:
/xyz/.test(function(){ xyz; }) ? /\b_super\b/ : /.*/;
"." -> 匹配除“\n”之外的任何单个字符。若要匹配包括“\n”在内的任意字符,请使用诸如“[\s\S]”之类的模式。
"\b" -> 匹配一个字的边界,即字与空格间的位置。例如,“er\b”匹配“never”中的“er”,但不匹配“verb”中的“er”。
因此上面的/\b_super\b/正则,只匹配_super,而.*_super.*,都不会匹配。
/.*/匹配除了“\n”之外的任何字符。
一般情况下,Function.prototype.toString 会显示函数里面的字符串,比如:function(){ xyz; },会显示成"function(){ xyz; }",这时通过/xyz/.test会返回真。但是safari,mobile opera等浏览器无法显示。
所以上面的代码的意思:当函数里面的内容可以显示时,test就会返回真,然后就返回可以判断函数里面是否有_super属性的正则表达式,否则就返回一个不管判断什么字符都返回true的正则表达式.
这个方法一般在继承中使用,比如,子类继承父类,子类在添加方法时,会先检查之前是否已经有了此方法名,如果有,会先判断此方法是否是父类的,这时就可以通过判断函数里面是否存在_super的字样,如果有,就证明是父类的,就需要重写。没有的话,就说明是子类之前已经添加的,就不需要添加了。
"<",">"操作
var a = {
valueOf:function(){return 1}
};
var b = {
valueOf:function(){return 2}
};
a < b; //true
"<",">"操作,强制计算前后对象的值,然后比较大小,对象会先调用自身的valueOf方法,也就是调用a,b对象的valueOf方法。
callee,caller的区别
callee是arguments对象的一个属性,它指向的是当前函数。比如:function a(){ arguments.callee ->a }。
caller是调用函数的函数,比如:function a (){} function b(){ a(); },b()。当调用b时,b里面会调用a.这时a.caller指的就是b。如果函数是由顶层调用的,那么 caller 包含的就是 null。不过这个属性已经在es5中被废弃的,所以面试官如果问这个,我会觉得面试官在显摆。
司徒正美的这本书在讲数据属性和访问器属性时,讲的没有js高级程序设计的好,建议大家去看js高级程序设计里面的那一章。讲的是一些Object.defineProperty,Object.freeze等es5的东西,它能够操作js对象里面的内部属性,当然低版本IE浏览器是不支持的。所以一般用的比较少,除了一些简单的可以用低版本IE模拟的功能(Object.defineProperty)才会使用到,其他功能用的非常非常少。了解就好。
加油!
第九课:js的类与继承的更多相关文章
- js面向对象--类式继承
		//待研究//类式继承 //js中模拟类式继承的3个函数 //简单的辅助函数,让你可以将新函数绑定到对象的 prototype 上 Function.prototype.method = functi ... 
- js的类和继承
		因为我使用java语言入门的编程,所以对javascript的类和继承有种想当然一样,或者是差不多的感觉,但实际上两者还是有很多不同的 首先我们说类,javascript中类的实现是基于原型继承机制的 ... 
- js 创建类和继承的几种方法
		在面向对象编程中,类(class)是对象(object)的模板,定义了同一组对象(又称"实例")共有的属性和方法.JavaScript语言里是没有类的概念的,但是我们通过以下方法也 ... 
- javascript“类”与继承总结和回顾
		Javascipt语法不支持"类"(class)[es6已经支持],但是有模拟类的方法.今天我主要谈谈Javascipt中模拟“类”的方法及js中继承的总结和回顾. js中实现“类 ... 
- JS原型继承和类式继承
		前言 一个多月前,卤煮读了一篇翻译过来的外国人写的技术博客.此君在博客中将js中的类(构造)继承和原型继承做了一些比较,并且得出了结论:建议诸位在开发是用原型继承.文中提到了各种原型继承的优点,详细的 ... 
- js类(继承)(二)
		1. 定义js类 js并不是一种面向对向的语言, 没有提供对类的支持, 因此我们不能像在传统的语言里那样 用class来定义类, 但我们可以利用js的闭包封装机制来实现js类, 我们来封装一个简的Sh ... 
- JS面向对象组件 --  继承的其他方式(类式继承、原型继承)
		继承的其他形式: •类式继承:利用构造函数(类)继承的方式 •原型继承:借助原型来实现对象继承对象 类 : JS是没有类的概念的 , 把JS中的构造函数看做的类 要做属性和方法继承的时候,要分开继 ... 
- js模块,类,继承,命名空间,私有属性等相关概念梳理
		js确切的说是一种基于对象的语言,和纯面向对象的语言(比如as)稍微有点区别,js中没有类的概念.虽然有继承但是基于原型的继承.随着前段越来越受重视,jser们利用js的一些特性他们制造出了和纯面向对 ... 
- js原生设计模式——2面向对象编程之继承—原型继承(类式继承的封装)
		<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&qu ... 
随机推荐
- seq 显示00  01的格式
			for i in `seq -w 00 20` ; do echo $i ;done 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 ... 
- codeforces 709B B. Checkpoints(水题)
			题目链接: B. Checkpoints 题意: 给了n个点,现在给一个起点,问最少访问n-1个点的最小行走距离是多少; 思路: 分情况讨论就好了; AC代码: #include <iostre ... 
- HDU 2669 Romantic【扩展欧几里德】
			裸的扩展欧几里德,求最小的X,X=((X0%b)+b)%b,每个X都对应一个Y,代入原式求解可得 #include<stdio.h> #include<string.h> ty ... 
- 使用PS3手柄在PC玩Unity3D游戏
			PS3手柄玩Unity游戏 今天把公司的PS3手柄接到PC上,想用手柄试一下玩赛车的感觉,老感觉用键盘按键玩的不爽. 把PS3的手柄接到PC上之后,系统提示正在安装驱动--,百度找资料,如何在PC上使 ... 
- HTML5之应用缓存---manifest---缓存使用----HTML5的manifest缓存
			相信来查这一类问题的都是遇到问题或者是初学者吧! 没关系相信你认真看过之后就会知道明白的 这是HTML5新加的特性 HTML5 引入了应用程序缓存,这意味着 web 应用可进行缓存,并可在没有因特网连 ... 
- 学员信息录入(StuInfoManager)   用分层实现(既MySchool后的一个案例)
			数据库 数据表名 Student 中文表名 学员信息表 字段显示 字段名 数据类型 字段大小 备注和说明 编号 stu_id int 主键,自增1 学生姓名 stu_name varchar 50 不 ... 
- Hill密码
			希尔密码(Hill Password)是运用基本矩阵论原理的替换密码,由Lester S. Hill在1929年发明.每个字母当作26进制数字:A=, B=, C=... 一串字母当成n维向量,跟一个 ... 
- throw跟throws关键字
			throws关键字 定义一个方法的时候可以使用throws关键字声明.使用throws关键字声明的方法表示此方法不处理异常,而交给方法调用处进行处理. throws关键字格式: public 返回值类 ... 
- CSS padding margin border属性
			主要定义四个区域:内容(content).内边距(padding).边框(border)和外边距(margin) margin:层的边框以外留的空白 background-color:背景颜色 bac ... 
- Python-执行系统命令
			执行系统命令 os.system os.spawn* os.popen popen2.* commands.* 后面三个已经废弃,以上执行shell命令的相关的模块和函数的功能均在subprocess ... 
