实例详解-类(一):
//每个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学习笔记-实例详解-类(一)的更多相关文章

  1. JavaScript学习笔记-实例详解-类(二)

    实例详解-类(二)   //===给Object.prototype添加只读\不可枚举\不可配置的属性objectId(function(){ Object.defineProperty(Object ...

  2. Java程序猿的JavaScript学习笔记(10—— jQuery-在“类”层面扩展)

    计划按例如以下顺序完毕这篇笔记: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScript ...

  3. Angular6 学习笔记——路由详解

    angular6.x系列的学习笔记记录,仍在不断完善中,学习地址: https://www.angular.cn/guide/template-syntax http://www.ngfans.net ...

  4. Angular6 学习笔记——组件详解之组件通讯

    angular6.x系列的学习笔记记录,仍在不断完善中,学习地址: https://www.angular.cn/guide/template-syntax http://www.ngfans.net ...

  5. Angular6 学习笔记——组件详解之模板语法

    angular6.x系列的学习笔记记录,仍在不断完善中,学习地址: https://www.angular.cn/guide/template-syntax http://www.ngfans.net ...

  6. Android学习笔记-Dialog详解

    1.对话框的使用 1.1AlertDialog的显示 简单对话框以及监听的设置:重点掌握三个按钮(也就是三上单词): PositiveButton(确认按钮);NeutralButton(忽略按钮) ...

  7. C++并发与多线程学习笔记--unique_lock详解

    unique_lock 取代lock_quard unique_lock 的第二个参数 std::adopt_lock std::try_to_lock std::defer_lock unique_ ...

  8. SIP学习(实例详解)

    本文摘自:http://blog.chinaunix.net/uid-20655530-id-1589483.html 学习 SIP 协议最快捷的方法是通过范例来学习, 找到了一个完整的呼叫流程,le ...

  9. [CSS3] 学习笔记-选择器详解(三)

    1.UI元素状态伪类选择器 在CSS3的选择器中,除了结构性伪类选择器外,还有一种UI元素伪类选择器.这些选择器的共同特征是:指定的样式只有当元素处于某种状态时才起作用,在默认状态下不起作用.在CSS ...

随机推荐

  1. java二维数组的常见初始化

    public class Test{ public static void main(String[] args){ //第一种: //int[][] arr1 = new int[][]{{1,2} ...

  2. GitHub入门教程 Hello World for GitHub

          Intro                              1.简介 What is GitHub?           2.什么是github? Create a Reposi ...

  3. linux下查看进程占用端口和端口占用进程命令

    Linux下查看进程占用端口: 查看程序对应进程号:ps –ef|grep 进程名 REDHAT :查看进程号所占用的端口号:netstat –nltp|grep 进程号 ubuntu:查看进程占用端 ...

  4. 从css3书写顺序引出来的border-radius参数

    本鱼表示偶已经不会取标题了... 当时写这篇文章主要是想探讨一下优雅降级和渐进增强的区别,按照正常的逻辑思维,不管是降级还是增强,应该对于效果是没什么区别的,因为后者会覆盖前者,但今天无意看到张鑫旭的 ...

  5. wordpress和普通网页如何使用百度分享组件

    百度分享组件是什么?摘自百度百科: 百度分享是一个提供网页地址收藏.分享及发送的WEB2.0按钮工具,网站的浏览者可以方便的分享到人人网.分享到开心网.分享到QQ空间.分享到新浪微博等一系列SNS站点 ...

  6. JAVA 设计模式 职责链模式

    用途 职责链模式 (Chain Of Responsibility) 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系. 将这个对象连成一条链,并沿着这条链传递该请求,直到有一个 ...

  7. Elasticsearch集群配置以及REST API使用

    ES安装与启动 在官网下载压缩包,解压后直接运行bin目录下的.bat文件即可.下载地址戳这里. ES配置集群 Elasticsearch配置集群很简单,只要配置一个集群的 名称 ,ES就会自动寻找并 ...

  8. 基于HT for Web 3D呈现Box2DJS物理引擎

    上篇我们基于HT for Web呈现了A* Search Algorithm的3D寻路效果,这篇我们将采用HT for Web 3D来呈现Box2DJS物理引擎的碰撞效果,同上篇其实Box2DJS只是 ...

  9. JS魔法堂:LINK元素深入详解

    一.前言 我们一般使用方式为 <link type="text/css" rel="stylesheet" href="text.css&quo ...

  10. 八、RFCOMM

    1.      RFCOMM 先来看看RFCOMM在协议栈层次体系中的位置.从下图可以看出RFCOMM处于传输层.与AVCTP,TCS-BIN处于同一层次.处于其上层的会话层中的OBEX,SPP等大部 ...