引言
1、所有的编程语言按照数据类型大体可以分为两类:
一类是静态类型语言,另一类是动态类型语言。 静态类型语言在编译的时候呢,我们已经确定的变量的类型。而动态类型语言。它的变量类型要到程序运行的时候,等待变量被赋予某一个值之后,才会具有某种类型; 在js当中,当我们对一个变量赋值的时候,我们不需要考虑它的的类型。因此,JavaScript是一门典型的动态类型的类型语言
var duck= {
duckSing : function ( ) {
console. log ( '嘎嘎嘎' ) ;
}
}
var chicken= {
duckSing : function ( ) {
console. log ( '嘎嘎嘎' ) ;
}
}
var choir= [ ] ;
var joinChoir = function ( animal ) {
if ( animal&& typeod ( animal. duckSing) === 'function' ) {
choir. push ( animal) ;
console. log ( '恭喜加入合唱团' ) ;
}
}
2、定义类的基本写法
2.1使用构造函数来定义类
JavaScript推荐使用构造函数来定义类。就是写一个鬼知道(constrctor),然后new 关键字对这个构造函数 进行实例化从而得到一个对象。 例如:我需要定义一个person infor的类别。他有这样的属性。name(姓名)gender(性别)。这样的字段
function ( ) {
this . name'' ;
this . gender= 0
}
var p= new PersonInfo ( ) ;
p. name= '哈哈' ;
p. gender= 0 ;
2.2编写方法
定义类之后,即可为它编写方法,具体的办法是在构造函数的原型当中增加函数。比如说我们给personInfor增加一个。Sayhi的方法。
function ( ) {
this . name'' ;
this . gender= 0
}
PersonInfo . prototype. sayHi = function ( ) {
var result= '你好,我叫' + this . name+ ',我的性别是' + this . gender;
console. log ( result) ;
}
3、基本写法的改进
3.1使用命名空间来避免全局名称的污染
为了避免全局名称的污染,可以使用命名空间机制。虽然JavaScript没有命名空间的语法,但是我们可以通过一些基础的方法去模拟这样的一个操作。
var JSnamespace= window. JSnamespace|| { } ;
JSnamespace. PersonInfo = function ( ) {
this . name'' ;
this . gender= 0
}
JSnamespace. PersonInfo . prototype= {
sayHi : function ( ) {
var result= '你好,我叫' + this . name+ ',我的性别是' + this . gender;
console. log ( result) ;
}
}
3.2改进构造函数
3.2.1构造函数参数、
一般来说我们可以通过构造函数添加参数的方法,来简化对象的创建和赋值。
var JSnamespace= window. JSnamespace|| { } ;
JSnamespace. PersonInfo = function ( name, gender ) {
this . name= name;
this . gender= gender|| 0
}
JSnamespace. PersonInfo . prototype= {
sayHi : function ( ) {
var result= '你好,我叫' + this . name+ ',我的性别是' + this . gender;
console. log ( result) ;
}
}
3.2.2拷贝构造函数
为了解决上述的亮点不足,且为的对象的赋值。推荐使用"拷贝构造函数"这种构造函数写法。
JSnamespace. PersonInfo = function ( params ) {
params= params|| { } ;
this . name= params. name;
this . gender= params. gender|| 0
}
JSnamespace. PersonInfo = function ( params= { } ) {
this . name= params. name;
this . gender= params. gender|| 0
}
var p= new JSnamespace. PersonInfo ( { 'name' : 'aaa' } )
3.3使用文档注释来改进代码的可读性。
/ @class
JavaScript 的命名空间
@abstract
/
var JSnamespace = window. JSnamespace || { } ;
/
@namespace: JSnamespace
@class : JSnamespace. PersonInfo
个人信息、构造函数的类
@params { object} 个人信息对象
@a { string} 测试
/
JSnamespace. PersonInfo = function ( params = { } , a ) {
this . name = params[ "name" ] ;
this . gender = params[ "gender" ] || 0 ;
} ;
/
个人信息、构造函数的类的原型属性
/
JSnamespace. PersonInfo . prototype = {
/
获取打招呼的 字符串
@return { string} 返回自我介绍的字符串
/
sayHi : function ( ) {
var result = '你好,我叫' + this . name + ',我的性别是' + this . gender;
return result;
}
}
3.4枚举
之前呢,我们对于性别处理的时候,我们使⽤的是直接使⽤数值代码来表示的。数值代码可读性⽐较差,并且 不太好维护。很多编程语⾔都有定义枚举类型的语法。来去解决这个问题。虽然 js 没有定义枚举类型的语法。 但是我们可以通过⼀些办法来去模拟这个操作。⽐如说,我们定义⼀个 Object 的变量。其中的字段呢就是各种 各样的枚举值。
/ @enum
性别代码 枚举类
/
JSnamespace. GenderCodr= {
/ 未知 /
'UNKMOWN' : 0 ,
'MALE' : 1
'FEMAILE' : 2
}
JSnamespace. PersonInfo = function ( params = { } ) {
this . name = params[ "name" ] ;
this . gender = params[ "gender" ] || JSnamespace. GenderCodr. UNKMOWN ;
} ;
var p= new JSnamespace. PersonInfo ( {
'name' : '张三' ,
'gender' : JSnamespace. GenderCodr. MALE
} )
JSnamespace. PersonInfo . prototype = function ( ) {
getGenderApp : function ( ) {
var result = '' ;
if ( JSnamespace. GenderCode. MALE == this . gender) {
result = '先⽣' ;
} else if ( JSnamespace. GenderCode. FEMAILE == this . gender) {
result = '⼥⼠' ;
}
return result;
} ,
sayHi : function ( ) {
var result = '您好,' + this . name + this . getGenderApp ( ) + ',欢迎光临红浪漫。' ;
return result;
}
}
4.封装
封装(encapsulation):封装是将程序按照⼀定的逻辑分成多个相互协作的部分。并且对外界提供稳定的部分,我 们要对外界暴露出来⽐较稳定的这⼀部分的接⼝。将改变的部分隐藏起来,隐藏在内部。外界只能通过暴露出 来的部分。想这个对象发送操作请求,从⽽享受对象提供出来的⼀些服务。我们不需要去关⼼。对象内部是如 何阳区运作的. 封装性体现在 2 个⽅⾯: 1.对外隐藏实际的细节,只能⽤专⻔约定的⽅法去操作。 2.对内能实 现变量的共享,⽤于实现⼀些⽐较复杂的逻辑。
4.1私有静态变量
在 js 中可以使⽤"⽴即执⾏函数"(⾃执⾏函数)来隐藏私有变量,这个⽅法很适⽤于在对象的封装上。
var JSnamespace = window. JSnamespace || { } ;
JSnamespace. GenderCode = {
/ 未知 /
UNKNOWN : 0 ,
MALE : 1 ,
FEMAILE : 2
} ;
JSnamespace. PersonInfo = function ( params = { } ) {
this . name = params[ "name" ] ;
this . gender = params[ "gender" ] || JSnamespace. GenderCode. UNKNOWN ;
} ;
( function ( ) {
/
@static @private
/
var H_HelloWord = "你好" ;
JSnamespace. PersonInfo . prototype = {
getGenderApp : function ( ) {
var result = "" ;
if ( JSnamespace. GenderCode. MALE == this . gender) {
result = "先⽣" ;
} else if ( JSnamespace. GenderCode. FEMAILE == this . gender) {
result = "⼥⼠" ;
}
return result;
} ,
sayHi : function ( ) {
var result = H_HelloWord + this . name + this . getGenderApp ( ) + ",欢迎光临红浪漫。" ;
return result;
}
} ;
} ) ( ) ;
将私有变量与 prototype ⽅法。绑定代码都放到⽴即执⾏函数中。这样的写法的优点:
1.实现了封装性。私有变 量只能在这个⽴即执⾏函数的内部去使⽤,不会暴露到外部。 2.实现了变量的共享。可以使我们的 sayHi()⽅法 能访问到私有静态变量。 H_HelloWord 3.同⼀个类的⽅法。定义都写在⼀个⼤括号⾥⾯。提⾼代码的可读性。 按照⾯向对象编程的定义,H_HelloWord 实际上是⼀个静态私有变量.
4.2私有成员函数
( function ( ) {
/
@static @private
/
var H_HelloWord = "你好" ;
var getGenderApp = function ( gender ) {
var result = "" ;
if ( JSnamespace. GenderCode. MALE == gender) {
result = "先⽣" ;
} else if ( JSnamespace. GenderCode. FEMAILE == gender) {
result = "⼥⼠" ;
}
return result;
} ;
JSnamespace. PersonInfo . prototype = {
sayHi : function ( ) {
var result = H_HelloWord + this . name + this . getGenderApp ( ) + ",欢迎光临红浪漫。" ;
return result;
}
} ;
} ) ( ) ;
4.3公开静态成员
静态成员是属于整个类的,⽽不是某⼀个对象实例的。因此有些时候呢,是需要将静态成员公开给外部去使⽤ 的。对于⼤多数的⾯向对象的编程语⾔,我们可以使⽤"类.成员⽅法"。这样的语法来去使⽤静态成员。
var JSnamespace = window. JSnamespace || { } ;
/ @enum
性别代码 枚举类
/
JSnamespace. GenderCode = {
/ 未知 /
UNKNOWN : 0 ,
MALE : 1 ,
FEMAILE : 2
} ;
JSnamespace. PersonInfo = function ( params = { } ) {
this . name = params[ "name" ] ;
this . gender = params[ "gender" ] || JSnamespace. GenderCode. UNKNOWN ;
} ;
( function ( ) {
var say_hi_word = "你好" ;
JSnamespace. PersonInfo. getSayHiWord = function ( ) {
return say_hi_word + 'a' ;
} ;
JSnamespace. PersonInfo. setSayHiWord = function ( word ) {
say_hi_word = word;
} ;
} ) ( ) ;
5.继承
继承(inherit),也称之为叫派⽣。继承关系中,被继承的称之为⽗类或者(基类)。从⽗类继承⽽来的,被称之 为⼦类(或者派⽣类)。继承是保持对象之间的差异性的同时共享对象相似的属性的复⽤。 被继承的类总是有⼀些他所抽象的那⼀类事物的共同特点。继承实际上是提供了复⽤。只要从⼀个类继承,我 们就拥有了这个类的所有的⾏为或者属性。语义上的继承那表示是⼀种是什么is-a关系。
var JSnamespace = window. JSnamespace || { } ;
/ @enum
性别代码 枚举类
/
JSnamespace. GenderCode = {
/ 未知 /
UNKNOWN : 0 ,
MALE : 1 ,
FEMAILE : 2
} ;
JSnamespace. PersonInfo = function ( params = { } ) {
this . name = params[ "name" ] ;
this . gender = params[ "gender" ] || JSnamespace. GenderCode. UNKNOWN ;
} ;
( function ( ) {
var say_hi_word = "你好" ;
JSnamespace. PersonInfo. getSayHiWord = function ( ) {
return say_hi_word;
}
JSnamespace. PersonInfo. setSayHiWord = function ( word ) {
say_hi_word = word;
}
} ) ( ) ;
JSnamespace. Employee = function ( params = { } ) {
JSnamespace. PersonInfo . call ( this , {
"name" : params[ 'name' ] ,
"gender" : params[ 'gender' ]
} ) ;
this . email = params[ 'email' ] ;
} ;
var e = new JSnamespace. Employee ( {
'email' : '417458052@qq.com'
} )
多态