面向对象的特点
- 抽象:提取出主要特征。
- 封装: 看不到里面,用好表面的功能。
- 继承:从父类继承出一些方法和属性,子类又有一些自己的特性。
- 多重继承
- 多态
对象的组成
- 方法(函数:自由;方法:属于一个对象)
- 属性
This:当前的方法属于谁。
创建对象:
//最基础的创建对象--使用此方式创造多个对象会疯
var obj = new Object();
obj.name = "Herman";
obj.sayName = function() {
console.log(this.name);
};
obj.sayName(); //Herman
工厂模式
//解决创建多个对象的问题,可以想到用函数将上面代码包起来,将变量作为参数传到对象中。这个函数叫做构造函数(可以理解为构造出对象的函数)。这种模式被称为工厂模式。
function createPerson(name) {
var obj = new Object(); //工厂的原料
obj.name = name; //加工
obj.sayName = function() { //加工
console.log(this.name);
};
return obj; //出厂
}
var p1 = createPerson('Herman');
p1.sayName();
问题:
- 没有new。加上new后,会创建一个空白对象并返回这个对象。
- 函数重复定义--资源浪费
p1.sayName == p2.sayName //false
解决没有new的问题:
function createPerson(name) {
//调用函数,前面加上new的时候,js会在这里new一个空白对象:var this = new Object()
this.name = name;
this.sayName = function() {
console.log(this.name);
};
//调用函数,前面加上new,js会在这儿返回这个对象:return this
}
var p1 = new createPerson('Herman'); //调用函数,前面加上new。
var p2 = new createPerson('Allen');
p1.sayName();
p2.sayName();
p1.sayName === p2.sayName; //false
解决函数重复的问题:
function CreatePerson(name) {
//调用函数,前面加上new的时候,js会在这里new一个空白对象:var this = new Object()
this.name = name;
//调用函数,前面加上new,js会在这儿返回这个对象:return this
}
CreatePerson.prototype.sayName = function() {
console.log(this.name);
}
var p1 = new CreatePerson('Herman');
var p2 = new CreatePerson('Allen');
p1.sayName();
p2.sayName();
p1.sayName === p2.sayName; //true
在构造函数加属性,在原型上加方法。此方式称为混合模式。
例:选项卡
<style>
#tabs a {
border:1px solid #ddd;
padding:2px 6px;
cursor: pointer;
}
#tabs .active {
background-color: purple;
color: #fff;
}
#tabs p {
display: none;
background-color: #efefef;
border: 1px solid #eee;
width: 200px;
height: 200px;
}
</style>
<div id="tabs">
<a class="active">one</a>
<a>two</a>
<a>three</a>
<p style="display: block">ONE.ONE.</p>
<p>TWO.TWO.TWO</p>
<p>THREE.THREE.</p>
</div>
实现选项卡功能:
// window.onload = function() {
// let oTabs = document.getElementById('tabs');
// let oBtn = oTabs.getElementsByTagName('a');
// let oContent = oTabs.getElementsByTagName('p');
// for(let i=0; i<oBtn.length; i++) {
// oBtn[i].index = i;
// oBtn[i].onclick = function() {
// for(let j=0; j<oBtn.length; j++) {
// oBtn[j].className = '';
// oContent[j].style.display = 'none';
// }
// this.className = 'active';
// oContent[this.index].style.display = 'block';
// }
// }
// }
//通过面向对象实现
window.onload = function() {
let ct = new ChangeTabs('tabs');
};
function ChangeTabs(id) {
let _this = this;
let oTabs = document.getElementById(id);
this.oBtn = oTabs.getElementsByTagName('a');
this.oContent = oTabs.getElementsByTagName('p');
for(let i=0; i<this.oBtn.length; i++) {
this.oBtn[i].index = i;
this.oBtn[i].onclick = function() { //事件处理函数,this指向a标签。
_this.fnClick(this) //将this对象传给fnClick
};
};
};
ChangeTabs.prototype.fnClick = function(oBtn) {
for(let j=0; j<this.oBtn.length; j++) { //this指向实例对象。
this.oBtn[j].className = '';
this.oContent[j].style.display = 'none';
}
oBtn.className = 'active';
this.oContent[oBtn.index].style.display = 'block';
};
========================================
JSON对象-单体
整个程序只有一个,写起来简单。
命名空间:将方法包在一个JSON中,避免函数命名冲突。
继承
call 可以改变函数在执行时的this
function show() {
console.log(this.a)
};
show.call({a:'A'}) //A; this为{a:'A'}
function A() {
this.abc = 123;
};
function B() {
//这里会创建一个new B(),即this对象
A.call(this); //这个A中的this变成了B的this,然后再将这个this赋值为123.从而实现继承A中的属性。
}
var b = new B();
console.log(b.abc); //123
方法的继承通过浅拷贝方式。