JS面向对象高级篇

包装对象

JS基于原型的程序
基本类型都有自己的包装对象:
String Number Boolean

1
2
3
4
5
6
7
8
9
10
11
var str = 'hello';
str.charAt(0); //基本类型会找到对应的包装对象类型,然后包装对象把所有的属性和方法给了基本类型,然后包装对象消失
console.log(str.charAt(0)) //h
var str = 'hello';
str.number = 10;
console.log(str.number) //undefined
var str = 'hello';
String.prototype.number = 10;
console.log(str.number) //10

原型链

实例对象与原型之间的连接,叫做原型链
proto( 隐式连接 )
Object对象类型是原型链的最外层

1
2
3
4
5
6
function Adele() {}
Adele.prototype.age = 27;
Object.prototype.sex = 'man';
var adele = new Adele();
console.log(adele.age) //27
console.log(adele.sex) // man

面向对象的一些属性和方法
hasOwnProperty() : 看是不是对象自身下面的属性,在最外层Object下
constructor : 查看对象的构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Adele() {
this.profession = 'FE';
}
Adele.prototype.age = 27;
Object.prototype.sex = 'man';
var adele = new Adele();
console.log(adele.age) //27
console.log(adele.sex) // man
console.log(adele.profession) // FE
//hasOwnProperty()
console.log(adele.hasOwnProperty('profession')); //true
console.log(adele.hasOwnProperty('age')); //false
//constructor
console.log(adele.constructor); //Adele
console.log(adele.constructor == Adele);//true

constructor 需要注意到的地方

可用来判断是否为数组 ‘arr.constructor == Array’
每个原型都会自动添加constructor属性
For in 的时候有些属性是找不到的
避免修改construtor属性

1
2
3
4
5
6
7
8
9
10
11
function Adele() {}
//JSON写法会覆盖constructor属性,需要指正
Adele.prototype = {
//修正constructor属性
constructor : Adele,
name : 'Adai',
age : '27',
sex : 'man'
}
var adele = new Adele();
console.log(adele.constructor);

instanceof : 运算符
判断对象与构造函数在原型链上是否有关系
可以做类型判断 arr instanceof Array
toString() : 系统对象下面都是自带的 , 自己写的对象都是通过原型链找object下面的
有以下几种应用

  1. 把对象转成字符串
1
2
3
4
5
6
var arr = [1,2,3];
console.log( arr.toString() ); //1,2,3
Array.prototype.toString = function(){
return this.join('+');
};
console.log( arr.toString() ); //'1+2+3'
  1. 进制转换
1
2
var num = 255;
console.log( num.toString(16) ); //'ff'
  1. 类型判断(一般都用这种方法判断是否为数组)
1
2
3
var arr = [];
console.log( Object.prototype.toString.call(arr)); //[object Array]
console.log( Object.prototype.toString.call(arr) == '[object Array]' ); //tru

三种判断数组的方法

1
2
3
4
5
6
7
8
var oF = document.createElement('iframe');
document.body.appendChild( oF );
var ifArray = window.frames[0].Array;
var arr = new ifArray();
console.log( arr.constructor == Array ); //false
console.log( arr instanceof Array ); //false
console.log( Object.prototype.toString.call(arr) == '[object Array]' ); //true

什么是继承

子类不影响父类,子类可以继承父类的一些功能 (代码复用 )
属性的继承 : 调用父类的构造函数 call
方法的继承 : 把父类原型赋给子类原型(不靠谱)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function Adele (name, sex) {
this.name = name;
this.sex = sex;
}
Adele.prototype.showName = function () {
console.log(this.name);
}
var adele = new Adele('Adai', '男');
adele.showName(); //Adai
function Adai(name, sex, job) { // 子类
Adele.call(this, name, sex); //用call修改this指向
this.job = job;
}
//方法继承1: 把父类原型赋给子类原型
Adai.prototype = Adele.prototype;
//对象赋值不仅是值的复制,而且也是引用的传递(子类会影响父类)
Adai.prototype.showSex = function () {
console.log(this.sex); //父类引用子类方法
}
var adai = new Adai('xiaobai', '女', 'FE');
adai.showName();//xiaobai
adai.showSex();//女
adele.showSex();//男

方法的继承 :
for in : 拷贝继承 (jquery也是采用拷贝继承extend)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function Adele (name, sex) {
this.name = name;
this.sex = sex;
}
Adele.prototype.showName = function () {
console.log(this.name);
}
var adele = new Adele('Adai', '男');
adele.showName(); //Adai
function Adai(name, sex, job) { // 子类
Adele.call(this, name, sex); //用call修改this指向
this.job = job;
}
extend(Adai.prototype, Adele.prototype);
Adai.prototype.showName = function () {
console.log(this.sex);
}
var adai = new Adai('xiaobai', '女', 'FE');
adai.showName();//女
adele.showName();//Adai
function extend(obj1,obj2){
for(var attr in obj2){
obj1[attr] = obj2[attr]; //拷贝继承
}
}

继承的其他形式
类式继承
利用构造函数(类)继承的方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Adele() { //父类
this.name = 'xiaobai';
}
Adele.prototype.showName = function () {
console.log(this.name);
};
function Adai() { //子类
Adele.call(this);
}
var F = function() {};
F.prototype = Adele.prototype;
Adai.prototype = new F(); //和Adele原型方法形成链接,抛开属性
Adai.prototype.constructor = Adai; //修正constructor指向问题否则将指向Adele
var a2 = new Adai();
a2.showName(); //xiaobai
console.log(a2.name); //xiaobai

原型继承
借助原型来实现对象继承对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var a = {
name : 'Adele'
};
var b = cloneObj(a);
b.name = "xiaobai";
console.log(b.name);
console.log(a.name);
//原型继承封装函数
function cloneObj(obj) {
var F = function() {};
F.prototype = obj;
return new F();
}

三个继承方式的区别
拷贝继承: 通用型的 有new或无new的时候都可以
类式继承: new构造函数
原型继承: 无new的对象