javascript的函数、创建对象、封装、属性和方法、继承
转自原文javascript的函数、创建对象、封装、属性和方法、继承
一,function 
从一开始接触到js就感觉好灵活,每个人的写法都不一样,比如一个function就有N种写法 如:function showMsg(){},var showMsg=function(){},showMsg=function(){}
似乎没有什么区别,都是一样的嘛,真的是一样的吗,大家看看下面的例子.
//函数定义:命名函数(声明式),匿名函数(引用式)
//声明式,定义代码先于函数执行代码被解析
function t1(){
dwn("t1");
}
t1();
function t1(){
dwn("new t1");
}
t1();
//引用式,在函数运行中进行动态解析
var t1=function(){
dwn("new new t1");
}
t1();
var t1=function(){
dwn("new new new t1");
}
t1();
//以上输出:new t1,new t1,new new t1,new new new t1
可能想着应该是输出t1,new t1,new newt1,new new new t1,结果却并不是这样,应该理解这句话:声明
式,定义代码先于函数执行代码被解析 
如果深入一步,应该说是scope链问题,实际上前面两个方法等价于window.t1,可以理解为t1是window的
一个公有属性,被赋了两次值,以最后一次赋值为最终值 
而后面两个方法,可以理解为是t1是个变量,第四个方法的var去掉之后的结果仍然不会改变 
然而,当第四个方法改成function t1(){}这样的声明式时,结果变成了new new new t1,new new new
t1,new new t1,new new t1 
前面两个按照我的理解可以很好的理解为什么是这个答案,第三个也可以理解,但是最后一个输出让我比
较纠结,希望有高手出现解答一下 
另外匿名函数还有(function(){...})()这样的写法,最后一个括号用于参数输入 
还有var t1=new function(){..}这样的声明,实际上t1已经是一个对象了
var t2 = new function()
{
var temp = 100; //私有成员
this.temp = 200; //公有成员,这两个概念会在第三点以后展开说明
return temp + this.temp;
} alert(typeof(t2)); //object
alert(t2.constructor()); //
除此之外,还有使用系统内置函数对象来构建一个函数,例:
var t3 = new Function('var temp = 100; this.temp = 200; return temp + this.temp;'); //这个位置加不加new结果都一样,WHY
alert(typeof(t3)); //function
alert(t3()); //300
二,创建对象 
首先我们理解一下面向对象编程(Object-Oriented Programming,OOP),使用OOP技术,常常要使用许多
代码模块,每个模块都提供特定的功能,每个模块都是孤立的,甚至与其它模块完全独立 
。这种模块化编程方法提供了非常大的多样性,大大增加了代码的重用机会。可以举例进一步说明这个问
题,假定计算机上的一个高性能应用程序是一辆一流赛车。如果使用传统的编程技巧,这辆赛车就是 
一个单元。如果要改进该车,就必须替换整个单元,把它送回厂商,让汽车专家升级它,或者购买一个新
车。如果使用OOP技术,就只需从厂商处购买新的引擎,自己按照说明替换它,而不必用钢锯切割车体。 
不过大部分的论点是,javascript并不是直接的面向对象的语言,但是通过模拟可以做到很多面向对象语
言才能做到的事,如继承,多态,封装,javascript都能干(没有做不到,只是想不到)
//以下三种构造对象的方法
//new Object,实例化一个Object
var a=new Object();
a.x=1,a.y=2;
//对象直接量
var b={x:1,y:2};
//定义类型
function Point(x,y){ //类似于C#中的类
this.x=x;
this.y=y;
}
var p=new Point(1,2); //实例化类
第一种方法通过构造基本对象直接添加属性的方法来实现,第二种和第一种差不多,可以看成是第一种方
法的快捷表示法 
第三种方法中,可以以”类“为基础,创造多个类型相同的对象
三,对象属性的封装(公有和私有) 
以例子来说明 
function List(){ 
var m_elements=[]; //私有成员,在对象外无法访问,如果此处无var声明,则m_elements将变成全局变
量,这样外部是可以直接访问到的,如alert(m_elements[0])
m_elements=Array.apply(m_elements,arguments);
//此处模拟getter,使用时alist.length;
//等价于getName()方式:this.length=function(){return m_elements.length;},使用时 alist.length();
//公有属性,可以通过"."运算符或下标来访问
this.length={
valueOf:function(){
return m_elements.length;
},
toString:function(){
return m_elements.length;
}
}
//公有方法,此方法使用得alert(alist)相当于alert(alist.toString())
this.toString=function(){
return m_elements.toString();
}
//公有方法
this.add=function(){
m_elements.push.apply(m_elements,arguments);
}
//私有方法如下形式,这里涉及到了闭包的概念,接下来继续说明
//var add=function()或function add()
//{
//m_elements.push.apply(m_elements,arguments);
//}
}
var alist=new List(1,2,3);
dwn(alist); //=alert(alist.toString()),输出1,2,3
dwn(alist.length); //输出3
alist.add(4,5,6);
dwn(alist); //输出1,2,3,4,5,6
dwn(alist.length); //输出6
四,属性和方法的类型 
javascript里,对象的属性和方法支持4种不同的类型:private property(私有属性),dynamic public
property(动态公有属性),static public property/prototype property(静态公有属性或原型属性), 
static property(静态属性或类属性)。私有属性对外界完全不具备访问性,可以通过内部的getter和
setter(都是模拟);动态公有属性外界可以访问,每个对象实例持有一个副本,不会相互影响;原型 
属性每个对象实例共享唯一副本;类属性不作为实例的属性,只作为类的属性。 
以下是例子:
//动态公有类型,静态公有类型(原型属性)
function myClass(){
var p=100; //private property
this.x=10; //dynamic public property
}
myClass.prototype.y=20; //static public property or prototype property,动态为myClass的原型添 加了属性,将作用于所有实例化了的对象,注意这里用到了prototype,这是一个非常有用的东东
//要想成为高级javascript阶段,prototype和闭包必须得理解和适当应用
myClass.z=30; //static property var a=new myClass();
dwn(a.p) //undefined
dwn(a.x) //
dwn(a.y) //
a.x=20;
a.y=40;
dwn(a.x); //
dwn(a.y); //
delete(a.x); //删除对象a的属性x
delete(a.y); //删除对象a的属性y
dwn(a.x); //undefined
dwn(a.y); //20 静态公有属性y被删除后还原为原型属性y
dwn(a.z); //undefined 类属性无法通过对象访问
dwn(myClass.z);
五,原型(prototype) 
这里只讲部分,prototype和闭包都不是几句话都能讲清楚的,如果这里可以给你一些启蒙,则万幸矣 
习语”照猫画虎“,这里的猫就是原型,虎是类型,可以表示成:虎.prototype=某只猫 or
虎.prototype=new 猫() 
因为原型属性每个对象实例共享唯一副本,所以当实例中的一个调整了一个原型属性的值时,所有实例调
用这个属性时都将发生变化,这点需要注意 
以下是原型关系的类型链:
function ClassA(){
}
ClassA.prototype=new Object();
function ClassB(){
}
ClassB.prototype=new ClassA();
function ClassC(){
}
ClassC.prototype=new ClassB();
var obj=new ClassC();
dwn(obj instanceof ClassC); //true
dwn(obj instanceof ClassB); //true
dwn(obj instanceof ClassA); //true
dwn(obj instanceof Object); //true
带默认值的Point对象:
function Point2(x,y){
if (x) this.x=x;
if (y) this.y=y;
}
//设定Point2对象的x,y默认值为0
Point2.prototype.x=0;
Point2.prototype.y=0;
//p1是一个默认(0,0)的对象
var p1=new Point2(); //可以写成var p1=new Point2也不会出错,WHY
//p2赋值
var p2=new Point2(1,2);
dwn(p1.x+","+p1.y); //0,0
dwn(p2.x+","+p2.y); //1,2
delete对象的属性后,原型属性将回到初始化的状态:
function ClassD(){
this.a=100;
this.b=200;
this.c=300
}
ClassD.prototype=new ClassD(); //将ClassD原有的属性设为原型,包括其值
ClassD.prototype.reset=function(){ //将非原型属性删除
for (var each in this) {
delete this[each];
}
}
var d=new ClassD();
dwn(d.a); //
d.a*=2;
d.b*=2;
d.c*=2;
dwn(d.a); //
dwn(d.b); //
dwn(d.c); //
d.reset(); //删掉非原型属性,所有回来原型
dwn(d.a); //
dwn(d.b); //
dwn(d.c); //300 
六,继承 
如果两个类都是同一个实例的类型,那么它们之间存在着某种关系,我们把同一个实例的类型之间的泛化
关系称为继承。C#和JAVA中都有这个,具体的理解就不说了。 
在javascript中,并不直接从方法上支持继承,但是就像前面说的,可以模拟啊 
方法可以归纳为四种:构造继承法,原型继承法,实例继承法和拷贝继承法。融会贯通之后,还有混合继
续法,这是什么法,就是前面四种挑几种混着来~ 
以下例子来源于王者归来,其中涉及到了apply,call和一些Array的用法,有兴趣的可以自己在园子里搜索
一下 
1,构造继续法例子:
//定义一个Collection类型
function Collection(size)
{
this.size = function(){return size}; //公有方法,可以被继承
} Collection.prototype.isEmpty = function(){ //静态方法,不能被继承
return this.size() == 0;
} //定义一个ArrayList类型,它"继承"Collection类型
function ArrayList()
{
var m_elements = []; //私有成员,不能被继承
m_elements = Array.apply(m_elements, arguments); //ArrayList类型继承Collection
this.base = Collection;
this.base.call(this, m_elements.length); this.add = function()
{
return m_elements.push.apply(m_elements, arguments);
}
this.toArray = function()
{
return m_elements;
}
} ArrayList.prototype.toString = function()
{
return this.toArray().toString();
}
//定义一个SortedList类型,它继承ArrayList类型
function SortedList()
{
//SortedList类型继承ArrayList
this.base = ArrayList;
this.base.apply(this, arguments); this.sort = function()
{
var arr = this.toArray();
arr.sort.apply(arr, arguments);
}
} //构造一个ArrayList
var a = new ArrayList(1,2,3);
dwn(a);
dwn(a.size()); //a从Collection继承了size()方法
dwn(a.isEmpty); //但是a没有继承到isEmpty()方法 //构造一个SortedList
var b = new SortedList(3,1,2);
b.add(4,0); //b 从ArrayList继承了add()方法
dwn(b.toArray()); //b 从ArrayList继承了toArray()方法
b.sort(); //b 自己实现的sort()方法
dwn(b.toArray());
dwn(b);
dwn(b.size()); //b从Collection继承了size()方法
2,原型继承法例子:
//定义一个Point类型
function Point(dimension)
{ this.dimension = dimension;
} //定义一个Point2D类型,"继承"Point类型
function Point2D(x, y)
{
this.x = x;
this.y = y;
}
Point2D.prototype.distance = function()
{
return Math.sqrt(this.x * this.x + this.y * this.y);
}
Point2D.prototype = new Point(2); //Point2D继承了Point //定义一个Point3D类型,也继承Point类型
function Point3D(x, y, z)
{
this.x = x;
this.y = y;
this.z = z;
}
Point3D.prototype = new Point(3); //Point3D也继承了Point //构造一个Point2D对象
var p1 = new Point2D(0,0);
//构造一个Point3D对象
var p2 = new Point3D(0,1,2); dwn(p1.dimension);
dwn(p2.dimension);
dwn(p1 instanceof Point2D); //p1 是一个 Point2D
dwn(p1 instanceof Point); //p1 也是一个 Point
dwn(p2 instanceof Point); //p2 是一个Point
以上两种方法是最常用的 
3,实例继承法例子: 
在说此法例子之前,说说构造继承法的局限,如下:
function MyDate()
{
this.base = Date;
this.base.apply(this, arguments);
}
var date = new MyDate();
alert(date.toGMTString); //undefined,date并没有继承到Date类型,所以没有toGMTString方法
核心对象的某些方法不能被构造继承,原因是核心对象并不像我们自定义的一般对象那样在构造函数里进
行赋值或初始化操作 
换成原型继承法呢?,如下:
function MyDate(){} 
MyDate.prototype=new Date(); 
var date=new MyDate(); 
alert(date.toGMTString); //'[object]'不是日期对象,仍然没有继承到Date类型!
现在,换成实例继承法:
function MyDate()
{
var instance = new Date(); //instance是一个新创建的日期对象
instance.printDate = function(){
document.write("<p> "+instance.toLocaleString()+"</p> ");
} //对instance扩展printDate()方法
return instance; //将instance作为构造函数的返回值返回
}
var myDate = new MyDate();
dwn(myDate.toGMTString()); //这回成功输出了正确的时间字符串,看来myDate已经是一个Date的实例
了,继承成功 
myDate.printDate(); //如果没有return instance,将不能以下标访问,因为是私有对象的方法 
4,拷贝继承法例子:
Function.prototype.extends = function(obj)
{
for(var each in obj)
{
this.prototype[each] = obj[each];
//对对象的属性进行一对一的复制,但是它又慢又容易引起问题
//所以这种“继承”方式一般不推荐使用
}
}
var Point2D = function(){
//……
}
Point2D.extends(new Point())
{
//……
}
这种继承法似乎是用得很少的。 
5,混合继承例子:
function Point2D(x, y)
{
this.x = x;
this.y = y;
}
function ColorPoint2D(x, y, c)
{
Point2D.call(this, x, y); //这里是构造继承,调用了父类的构造函数
//从前面的例子看过来,这里等价于
//this.base=Point2D;
//this.base.call(this,x,y);
this.color = c;
}
ColorPoint2D.prototype = new Point2D(); //这里用了原型继承,让ColorPoint2D以Point2D对象为原型
javascript的函数、创建对象、封装、属性和方法、继承的更多相关文章
- JavaScript设置获取和设置属性的方法
		这篇文章主要介绍了JavaScript设置获取和设置属性的方法,学会使用getAttribute.setAttribute的用法,需要的朋友可以参考下 getAttribute 该方法用来获取元素 ... 
- javascript——对象的概念——函数 1 (函数对象的属性和方法)
		一.创建函数 函数是一种对象:Function类 是对象,可以通过 Function 实例化一个函数,不过最多的还是利用 function 来创建函数. 方式一:利用 Function类 来实例化函数 ... 
- JavaScript之Object对象常用属性与方法手册
		MDN Object参考地址:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Obje ... 
- 全面理解Javascript中Function对象的属性和方法
		http://www.cnblogs.com/liontone/p/3970420.html 函数是 JavaScript 中的基本数据类型,在函数这个对象上定义了一些属性和方法,下面我们逐一来介绍这 ... 
- javascript使用闭包模拟私有属性和方法
		最近因为做了一个项目,其中涉及到了js私有方法,这个概念在其语言里面是很常见的,很多语言都有private这个关键字,只要在一个类的前面加上private就表示申明了一个私有方法,但是javascri ... 
- javascript中的array对象属性及方法
		Array 对象 Array 对象用于在单个的变量中存储多个值. 创建 Array 对象的语法: new Array(); new Array(size); new Array(element0, e ... 
- 转载:js 创建对象、属性、方法
		1,自定义对象. 根据JS的对象扩展机制,用户可以自定义JS对象,这与Java语言有类似的地方. 与自定义对象相对应的是JS标准对象,例如Date.Array.Math等等. 2,原型(prototy ... 
- Javascript进阶:对象实例属性和方法
		Ecmascript中,Object类型是所有它的实例的基础.换句话说,Object类型所具有的任何属性和方法也同样存在于更具体的对象中. Object的每个实例都具有以下属性和方法,这些都能方便于我 ... 
- 【转】JavaScript 节点操作 以及DOMDocument属性和方法
		最近发现DOMDocument对象很重要,还有XMLHTTP也很重要 注意大小写一定不能弄错. 属性: 1Attributes 存储节点的属性列表(只读) 2childNodes 存储节点的子节点列表 ... 
- javascript面向对象方式,调用属性和方法
		1.定义一个Person类,其中的属性和方法如果想对外开放,需要使用this,如: var Person=function(name,age,sex){ var psex='Boy'; if(sex) ... 
随机推荐
- 3-4 第三天 Generator生成器
			Generator是ES6里面的新增规范,ES6其实就是ES2015.ES5.ES6.ES7这些术语大家上网一查就都明白了.JavaScript是一个范程,就是我们说的JS.ES就是ECMA Scri ... 
- selenium3 + python - xpath定位
			什么是xpath呢? 官方介绍:XPath即为XML路径语言,它是一种用来确定XML1(标准通用标记语言3的子集)文档中某部分位置的语言.反正小编看这个介绍是云里雾里的,通俗一点讲就是通过元素的路径来 ... 
- python 7:del 列表指定元素、list.pop(索引)、list.remove(元素值)(删除列表指定元素,且不可再使用;默认索引-1,弹出指定列表元素,可再使用;移除列表指定第一个元素)
			bicycles = ['trek', 'cannondale', 'redline', 'specialized'] print(bicycles) del bicycles[0] #删除指定列表元 ... 
- golang 获取statuscode
			最近日志打印的时候需要打印状态码,但是因为interface的原因直接获取失败,http.Request里面的response不知道怎么使用,所以就自己重写writeheader,write来截取st ... 
- dotnet core 发布配置(测试数据库和正式数据库自动切换)
			一.起源 在进行项目开发时,常常要求开发环境,测试环境及正式环境的分离,并且不同环境运行的参数都是不一样的,比如监听地址,数据库连接信息等.当然我们把配置信息保存到一个文件中,每次发布的时候,可以先修 ... 
- Android使用charles抓包
			1.下载并安状软件,官网在此: 2.前题条件,电脑和手机必须在同一网段 3.在Charles界面选择菜单 proxy->proxy settings 勾选"Enable transpa ... 
- 日期对话框(DatePickerDialog)和时间对话框(TimePickerDialog)
			效果图 布局 <Button android:id="@+id/btn_date" android:text="弹出日期选择对话框" android:la ... 
- poj1328  Radar Installation  区间贪心
			题目大意: 在X轴选择尽量少的点作为圆心,作半径为d的圆.使得这些圆能覆盖所有的点. 思路: 把每个点都转化到X轴上.也就是可以覆盖这个点的圆心的位置的范围[a,b].然后按照每个点对应的a从小到大排 ... 
- 分类(Category)的本质 及其与类扩展(Extension) /继承(Inherit)的区别
			1.分类的概念 分类是为了扩展系统类的方法而产生的一种方式,其作用就是在不修改原有类的基础上,为一个类扩展方法,最主要的是可以给系统类扩展我们自己定义的方法. 如何创建一个分类?↓↓ ()Cmd+N, ... 
- php判断方法及区别
			php判断方法 ‘is_类型名称’ php判断方法 $x="1"; echo gettype(is_string($x)); isset 是否存在 empty 是否 ... 
