面向对象之构造函数、实例对象、原型

一、面向对象
首先有一个需求,点击按钮改变div的样式。按照常规的思维来写,我们可能是先获取到目标元素,然后给目标元素添加事件,在事件中书写div需要改变的样式属性。如下:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript">
window.onload = function(){
var btn = document.getElementById('btn');
btn.onclick = function(){
var div = document.getElementById('div1');
div.style.height = '300px';
div.style.width = '300px';
div.style.backgroundColor = 'green';
}
}
</script>
</head>
<body>
<div style=" 200px;height: 200px;border:1px solid red;" id="div1"></div>
<input type="button" value="点击" id="btn">
</body>
</html>


但是随着事件的增多,代码的量也随之加大,如果点击的按钮不止一个,是不是又得将点击事件的代码重写一遍?这样维护起来也不方便;但如果换种思维考虑:是哪个元素要添加何种事件?这个事件是怎样的?就好比如何将大象装进冰箱,首先打开冰箱门,把大象装进去,关闭冰箱门;如果是一万头大象呢,是不是要开关一万次?这时要是大象来了冰箱门能自动开关就好了。所以,换种思维重写代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript">
window.onload = function(){
function ChangeStyle(divId,btnId){
//构造函数中this是谁?就是实例化对象cs
this.div = document.getElementById(divId);
this.btn = document.getElementById(btnId);
}
ChangeStyle.prototype.init = function(){
//原型方法里面this指向谁?就是具体的某个通过构造函数实例化的对象cs
var _this = this
this.btn.onclick = function(){
// 这个功能加到change方法里面,怎么办?
// this.style.backgroundColor = 'orange';
_this.change(this);
//假设这里的代码比价复杂,代码量比较大
}
}
ChangeStyle.prototype.change = function(obj){
//这里能得到按钮吗?
// this.btn.style.backgroundColor = 'orange';
obj.style.backgroundColor = 'pink';
this.div.style.width = '300px';
this.div.style.height = '300px';
this.div.style.border = '1px yellow solid';
this.div.style.backgroundColor = 'green';
} 
//...............
var cs = new ChangeStyle('div1','btn');
cs.init();
}
</script>
</head>
<body>
<div style=" 200px;height: 200px;border:1px solid red;" id="div1"></div>
<input type="button" value="点击" id="btn">
</body>
</html>


虽然就单一功能来讲,看似代码量要复杂一些,但是将来拓展功能,很多代码是可以复用的。相对于面向过程编程来讲,面向对象的在一定程度上避免了变量命名冲突,而且复用性强。
二、对象

所谓对象就是某种事物;JavaScript对象的实质是无序键值对的集合。产生对象的方式有两种:字面量和构造函数。
2.1字面量
通过各种数据类型的字面量表示:

var num = 12; var num = 1.2;

var str = 'hello'; var flag = true; 
var arr = [1,2,3]; var reg = /d+/; 
var obj = {};

//‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
var person = {}; 
person.name = '胡琦'; 
person.age = 18; 
person.sex = '男';

这里的数据类型可以是基本类型和引用类型。
2.2构造函数
内置对象和自定义对象;

var arr = new Array(); 
var obj = new Object();

var Obj = new RegExp('d+');
//‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
function Person(name,age){

this.name = name;
this.age = age; 
This.doing = function(){

console.log(this.name + ':撸码');

}

}

var p1 = new Person('胡琦',18);

三、函数
JavaScript中函数的三种角色:普通函数,作为构造函数,作为对象;

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <script type='text/javascript'>
//3.1普通函数


function foo(){ 'use strict'

console.log(this);

}

foo();//ES3中,this就是window;ES5的严格模式下,this为undefined


3.2对象方法


var obj = {}; obj.info = 'hello';

obj.showInfo = function(){ console.log(this.info);

}

foo.showInfo();//对象方法中的this就是调用方法的对象


//3.3构造函数


function Foo(info){ this.info = info;

this.showInfo = function(){ console.log(this.info);

}

}

Foo.prototype.fn = function(){ //原型对象中的this就是实例对象 console.log(this.info);

}

var foo = new Foo('hello'); foo.showInfo();//对象方法中的this就是实例对象


call/apply/bind
function foo(a,b){ console.log(a + b);

}

foo.call(null,1,2);

foo.apply(null,[1,2]); //改变this指向 var obj1 = {

info : 'Tom'

};

var obj2 = {

info : 'Jerry'

}

window.info = 'Spike';

var    showInfo = function(){ console.log(this.info);

};

showInfo();

showInfo.call(obj1);

showInfo.call(obj2);

//调用call或apply都会自动执行对应的函数,而bind不会执行对应的函数,只是返回了对函数的引用。


//高阶函数

//函数作为参数


function foo(fn) { var data = {

info: 'hello'

}

fn(data);

}

var    fn = function(data) { console.log(data.info);

};

foo(fn);


//函数作为返回值


function foo(){ var num = 1;

return function(){ return num++;

}

}

var fn = foo(); var r1 = fn(); var r2 = fn();

console.log(r1,r2);
 </script>
</head>
<body>

</body>
</html>

四、构造函数、实例对象、原型

4.1构造函数、原型与实例的关系

1.每个构造函数都有一个原型对象prototype

2.原型对象包含一个指向构造函数的指针constructor

3.原型对象都包含一个指向构造函数的内部指针__proto__


4.1.1 _proto__

在函数里有一个属性prototype
由该函数创建的对象默认会连接到该属性上
4.1.2 prototype与__proto__的关系

__proto__是站在对象角度来说的
prototype是站在构造函数角度说的

4.2原型链


原型链是一个由对象组成的有限对象链,用于实现继承和共享属性。

var obj = new Object();

对象是有原型对象的,原型对象也有原型对象
obj.__proto__.__proto__.__proto__

原型对象也有原型对象,对象的原型对象一直往上找,会找到一个null var arr = [];
arr -> Array.prototype -> Object.prototype -> null var o = new Object();
o -> Object.prototype -> null

 

function Foo1(){ this.name1 = '1';

}

function Foo2(){ this.name2 = '2';

}
Foo2.prototype = new Foo1(); function Foo3(){

this.name3 = '3';

}

Foo3.prototype = new Foo2(); var foo3 = new Foo3(); console.dir(foo3);

 

原型链:实例与原型的链条

foo3 -> foo2 -> foo1 -> Foo1.prototype -> Object.prototype -> null

原型链示例

var arr = [];

1.arr ‐> Array.prototype ‐> Object.prototype ‐> null var obj = {};
2.obj ‐> Object.prototype ‐> null

构造函数、实例对象、原型对象之间额关系:

 总结:

原文地址:https://www.cnblogs.com/hu-qi/p/5558027.html