JS面向对象及组件开发学习笔记(2)

JS是基于原型的程序

尽量不要去修改或者添加系统对象下面的方法和属性

包装对象

基本类型都有自己对应的包装对象:String Number Boolean(null undefined没有)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 var str = new String('hello');
alert(typeof str); //object
alert(str.charAt(1));
String.prototype.charAt = function(){};

var str = 'hello';
str.charAt(0); //基本类型会找到对应的包装对象类型,然后包装对象类型把所有的属性和方法给了基本类型,然后包装对象消失

var str = 'hello';
//给基本类型添加方法时,把方法添加到基本类型对应的包装对象上
String.prototype.lastValue = function(){
return this.charAt(this.length-1);
}
alert(str.lastValue()); //o

var str = 'hello';
str.number = 10;
alert(str.number); //undefined

原型链

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

hasOwnProperty和constructor的使用

面向对象的一些属性和方法
-hasOwnProperty():看是不是对象自身下面的属性

1
2
3
4
5
6
var arr = [];
arr.num = 10;
Array.prototype.num2 = 20;

alert(arr.hasOwnProperty('num')); //true
alert(arr.hasOwnProperty('num2')); //false

-constructor:查看对象的构造函数
每个原型都会自动添加constructor属性
For in 的时候有些属性是找不到的
避免修改constructor属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function A(){}
//A.prototype.constructor = A; 自动添加,constructor属性的值为构造函数A
var a1 = new A();
alert(a1.constructor); //A
alert(a1.hasOwnProperty == Object.prototype.hasOwnProperty); //true
var arr = [];
alert(arr.constructor == Array); //true

function Person(){}
Person.prototype.name = 'xiaoming';
Person.prototype.age = 20;
Person.prototype = {
constructor: Person, //这里需要添加这句话修正指向
name: 'xiaoming',
age: 20
};
for(var attr in Person.prototype){
alert(attr);
}
//系统自带的属性不能被for in到,自己添加的属性可以

-isntanseof:运算符
对象与构造函数在原型链上是否有关系
-toString():object上的方法

isntanseof类型判断

1
2
var arr = [];
alert(arr isntanseof Array); //true

利用toString做类型判断

1
2
3
4
5
6
7
8
9
10
11
12
var arr = [];
alert( Object.prototype.toString.call(arr) == '[object Array]' ); //true

window.onload = function(){
var oF = document.createElement('iframe');
document.body.appendChild(oF);
var ifArray = window.frames[0].Array;
var arr = new ifArray();
alert(arr.constructor == Array); //false
alert(arr isntanseof Array); //false
alert(Object.prototype.toString.call(arr) == '[object Array]'); //true
}

面向对象的继承

-在原有对象的基础上,略作修改,得到一个新的对象
-不影响原有对象的功能

子类不影响父类,子类可以继承父类的一些功能(代码复用)
属性继承:调用父类的构造函数 使用call改变this指向
方法继承: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
function CreatePerson(name, gender){
this.name = name;
this.gender = gender;
}
CreatePerson.prototype.showName = function(){
alert(this.name);
}
var p1 = new CreatePerson('xiaoming','male');
p1.showName();

function CreateStar(name, gender, job){
CreatePerson.call(this, name, gender);
this.job = job;
}
//CreateStar.prototype = CreatePerson.prototype; 这样会有对象引用问题
extend(CreateStar.prototype, CreatePerson.prototype);

var p2 = new CreateStar('xxx', 'male', 'actor');
p2.showName();

//对象拷贝会有引用问题,基本类型复制不会,可以通过把对象里的每一项赋给另一个对象的每一项
//函数虽然是对象类型,但是函数不能被修改,只能重新赋值
function extend(obj1, obj2){
for(var attr in obj2){
obj1[attr] = obj2[attr];
}
}

例子:继承的拖拽

继承的其他形式

-类式继承
利用构造函数(类)继承的方式
-原型继承
借助原型来实现对象继承对象

类式继承

JS中没有类的概念,把JS中的构造函数看作是类
属性和方法要分开继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function A(){
this.name = 'xiaoming';
}
A.prototype.showName = function(){
alert(this.name);
}

function B(){
A.call(this);
}

var F = function(){};
F.prototype = A.prototype;
B.prototype = new F();
B.prototype.constructor = B; //修正指向问题

var b1 = new B();
b1.showName();

原型继承

JS 拓展对象原型方法的正确姿势