JavaScript学习笔记-实例详解-类(一)
实例详解-类(一):
//每个javascript函数(除了bind())都自动拥有一个prototype对象
// 在未添加属性或重写prototype对象之前,它只包含唯一一个不可枚举属性constructor
// constructor的值是一个函数对象,指代函数对象自身(构造函数)
//原型对象是类的'唯一标识',而构造函数是类的'公共标识',因此这个constructor属性为对象提供了类
function Range(from,to){
this.from = from||0;
this.to = to||0;
}
console.log(Range.prototype.constructor); //[Function: Range] //未重写原型之前,它的constructor指代它自身
//==第一种方式:重写Range的原型对象prototype,若没有指定constructor属性,那么类将采用原型对象的默认原型Object类的constructor
Range.prototype = {
//====constructor:Range; //可以显式的给原型添加一个constructor构造函数,这里反向引用自身的构造函数
includes: function(x){return this.from<=x && x<=this.to;},
foreach: function(f){
for(var x = Math.ceil(this.from);x<=this.to;x++) f(x);
},
toString: function(){return '('+this.from+'...'+to+')';}
};
/*==第二种方式:除了显式的添加constructor,还可以使用预定义原型对象,它包含属性consturctor,然后逐个的给原型添加自定义的属性:
Range.prototype.includes = function(){...};
Range.prototype.foreach = function(){...};
Range.prototype.toString = functon(){...};
*/
var r = new Range(2,4);
console.log(r.constructor); //[Function: Object]
console.log(r.constructor === Object); //true //====这里的类F1和上面的类Range比较,
var F1 = function(){};
var p = {constructor:F1,a:1,b:2,c:function(){}}; //显式指定对象p的构造函数constructor为F1,若未指定则p.constructor===Object;
F1.prototype = p;
var p2 = new F1();
console.log(p2.constructor === p.constructor); //true 对象p2是类F1的实例,类F1重写了它的原型为对象p,所以对象p2继承了对象p的constructor;
console.log(p2.constructor === F1); //true
//====
var F2 = function(){};
//F2.sum = function(x,y){return x+y;}; //无效,不能直接为方法添加属性,只能通过它的原型对象为它添加属性
F2.prototype.sum = function(x,y){return x+y;};
var o = new F2();
console.log(o.constructor === F2); //true 因为F2使用自身的默认原型,它的constructor属性(构造函数)就是指代F2自身;
console.log(o.sum(1,2)); //3
//==========创建一个定义类的函数defineClass(函数式编程风格)=========================
function extend(o,p){ //定义一个复制对象属性的函数
for(var x in p){
o[x] = p[x];
}
return o;
}
function defineClass(constructor,methods,statics){ //该函数接收3个对象参数
if(methods) extend(constructor.prototype,methods); //添加所有实例属性
if(statics) extend(constructor,statics); //添加所有类属性
return constructor; //最后要返回构造函数
}
var Range1 = defineClass(
function(f,t){this.f=f;this.t=t;},
{
includes:function(x){return this.f<=x&&x<=this.t;},
toString:function(){return this.f+'...'+this.t;}
},
{
upto:function(t){return new Range1(0,t);}
}
);
var r3 = new Range1(5,7);
r3.includes(6);
console.log(r3.toString());
//==普通方法创建一个类:(调用时首先查找实例中是否直接定义了这个属性,有则返回实例属性;如果实例属性中没有就去构造函数中查找,有则返回;如果前面两者都没有就去原型对象中查找,如果没有则返回undefined)
//1.构造函数,定义对象属性
var Range2 = function(x,y){
if(isNaN(x)||isNaN(y)) throw new TypeError('not a number');
var self = this;
this.r = x;
this.i = y;
};
//2.原型属性(实例共享的属性、方法,通过实例对象来调用),也可将原型属性写进构造函数内动态的添加,但没创建一个实例就会执行一次,需要加判断是否已经创建;
Range2.prototype.add = function(that){return new Range2(this.r+that.r,this.i+that.i);};
Range2.prototype.mul = function(that){return new Range2(this.r*that.r,this.i*that.i);};
Range2.prototype.mag = function(){return Math.sqrt(this.r*this.r + this.i*this.i);};
Range2.prototype.neg = function(){return new Range2(-this.r,-this.i);};
Range2.prototype.toString = function(){return '{'+this.r+','+this.i+'}';};
Range2.prototype.equals = function(that){
return that != null &&
that.constructor === Range2 &&
this.r === that.r &&
this.i === that.i;
};
//3.类属性,方法(通过类直接调用)
Range2.ZERO = new Range2(0,0);
Range2.ONE = new Range2(1,0);
Range2.I = new Range2(0,1);
Range2._format = /^\{([^,] +),([^}] +)\}$/;
Range2.parse = function(s){
try{
var m = Range2._format.exec(s);
return new Range2(parseFloat(m[1],parseFloat(m[2])));
}catch(x){
throw new TypeError("can not parse");
}
};
//4.创建实例
var c = new Range2(2,3);
var d = new Range2(c.i, c.r);
//==可以随时为类(包括内置类)的原型扩展或更改属性,类的所有实例对象将随之改变==
Range2.prototype.divide = function(){return this.r-this.i;};
var str = c.add(d).toString();
console.log(Range2.ONE); //{ r: 1, i: 0 }
console.log(str); //{5,5}
//Range2.parse(c.toString()).add(c.neg()).equals(Range2.ZERO); //函数返回自身,可实现链式调用
//=========检测对象的类==========
//(一)o instanceof p 检测对象o是不是p得实例 ,
// (二) p.isPrototypeOf(o)检测p是不是o的原型,
// (三)有constructor的函数可通过他来判断属于哪个类
// 他们只能检测对象是否属于指定的类,而无法通过对象获得类名
//在客户端JS中,每个窗口/框架子页面都具有单独的执行上下文,每个上下文都包含独立的全局变量和一组独立的构造函数
// 他们之间的实例即使继承自相同的原型对象,但也是相互独立的原型对象,他们之间互不为实例
function typeAndValue(x){
if(x == null)return ''; //Null,undefined类型没有构造函数
switch (x.constructor){
case Number:return 'Number: '+x;
case String:return 'String: '+x;
case Date: return 'Date: ' +x;
case RegExp:return 'RegExp: '+x;
case Range2:return 'Renge2: '+x; //处理自定义类型
}
}
//(四)通过构造函数名字来识别对象的类(但并不是所有对象都有构造函数,并不是所有函数有名字)
function classof(o){
return Object.prototype.toString.call(o).slice(8,-1); //获取类名
}
Function.prototype.getName = function(){ //返回函数名字,可能为空,非函数返回null
if('name' in this) return this.name;
return this.name = this.toString().match(/function\s*([^(] *)\(/)[1];
};
function type(o){
var t, c,n;
if(o === null)return 'null'; //处理null值
if(o !== o ) return 'nan'; //处理NaN
if((t = typeof o) !== 'object') return t; //typeof可以辨认除了object之外的类型
if((c = classof(o)) !== 'Object') return c;//识别出大部分内置对象的类名,排除值为'Object'
if(o.constructor && typeof o.constructor === 'function' && //若构造函数名字存在则返回它
(n = o.constructor.getName())) return n;
return 'Object'; //其它无法判别的一律返回'Object'
}
//=========鸭式辩型:不需要特意去检测它是什么类,只检测它是否具备我们所需要的特性就行!
// "把会游泳,会嘎嘎叫的鸟都当着是鸭子对待!"
JavaScript学习笔记-实例详解-类(一)的更多相关文章
- JavaScript学习笔记-实例详解-类(二)
实例详解-类(二) //===给Object.prototype添加只读\不可枚举\不可配置的属性objectId(function(){ Object.defineProperty(Object ...
- Java程序猿的JavaScript学习笔记(10—— jQuery-在“类”层面扩展)
计划按例如以下顺序完毕这篇笔记: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScript ...
- Angular6 学习笔记——路由详解
angular6.x系列的学习笔记记录,仍在不断完善中,学习地址: https://www.angular.cn/guide/template-syntax http://www.ngfans.net ...
- Angular6 学习笔记——组件详解之组件通讯
angular6.x系列的学习笔记记录,仍在不断完善中,学习地址: https://www.angular.cn/guide/template-syntax http://www.ngfans.net ...
- Angular6 学习笔记——组件详解之模板语法
angular6.x系列的学习笔记记录,仍在不断完善中,学习地址: https://www.angular.cn/guide/template-syntax http://www.ngfans.net ...
- Android学习笔记-Dialog详解
1.对话框的使用 1.1AlertDialog的显示 简单对话框以及监听的设置:重点掌握三个按钮(也就是三上单词): PositiveButton(确认按钮);NeutralButton(忽略按钮) ...
- C++并发与多线程学习笔记--unique_lock详解
unique_lock 取代lock_quard unique_lock 的第二个参数 std::adopt_lock std::try_to_lock std::defer_lock unique_ ...
- SIP学习(实例详解)
本文摘自:http://blog.chinaunix.net/uid-20655530-id-1589483.html 学习 SIP 协议最快捷的方法是通过范例来学习, 找到了一个完整的呼叫流程,le ...
- [CSS3] 学习笔记-选择器详解(三)
1.UI元素状态伪类选择器 在CSS3的选择器中,除了结构性伪类选择器外,还有一种UI元素伪类选择器.这些选择器的共同特征是:指定的样式只有当元素处于某种状态时才起作用,在默认状态下不起作用.在CSS ...
随机推荐
- NYOJ 1023 还是回文(DP,花最少费用形成回文串)
/* 题意:给出一串字符(全部是小写字母),添加或删除一个字符,都会产生一定的花费. 那么,将字符串变成回文串的最小花费是多少呢? 思路:如果一个字符串增加一个字符 x可以形成一个回文串,那么从这个字 ...
- Oracle Concept
1. Truncate Truncate是DDL命令.表的物理位置是保存在数据字典中表的定义的一部分.首次创建时,在数据库的数据文件内给表分配了一个固定大小的空间.这就是所谓的区间并且为空.那么当插入 ...
- 深入解读A/B 测试的统计学原理
了解一些统计学知识对正确地进行 A/B 测试和研判试验结果是很有帮助的,本篇文章深入介绍了A/B 测试的原理和背后的统计学依据.完全理解本文中提到的数学计算需要你掌握概率方面的一点基础知识. 统计学在 ...
- Spark入门实战系列--5.Hive(上)--Hive介绍及部署
[注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 .Hive介绍 1.1 Hive介绍 月开源的一个数据仓库框架,提供了类似于SQL语法的HQ ...
- CSS好看的按钮
好看的按钮 <style> .btn { BORDER-RIGHT: #7b9ebd 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: #7b9ebd ...
- 原生JS编写的照片墙效果实例演示特效
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Android的UI设计与后台线程交互
本文将讨论Android应用程序的线程模型以及如何使用线程来处理耗时较长的操作,而不是在主线程中执行,保证用户界面(UI)的流畅运行.本文还将阐述一些用户界面(UI)中与线程交互的API.UI用户界面 ...
- SQL Server 2014里的针对基数估计的新设计(New Design for Cardinality Estimation)
对于SQL Server数据库来说,性能一直是一个绕不开的话题.而当我们去分析和研究性能问题时,执行计划又是一个我们一直关注的重点之一. 我们知道,在进行编译时,SQL Server会根据当前的数据库 ...
- [爬虫资源]各大爬虫资源大汇总,做我们自己的awesome系列
大数据的流行一定程序导致的爬虫的流行,有些企业和公司本身不生产数据,那就只能从网上爬取数据,笔者关注相关的内容有一定的时间,也写过很多关于爬虫的系列,现在收集好的框架希望能为对爬虫有兴趣的人,或者 ...
- [Server] 搭建发布环境Web Deploy
在Web Deploy前,实际上完全可以使用FTP方式发布网站. 如果你购买的只是虚拟空间,那FTP方式更广泛. 先来搭建一套FTP吧 添加FTP服务 在网站上添加FTP发布 配置FTP服务 FTP注 ...