一、面向对象
首先有一个需求,点击按钮改变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="width: 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="width: 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
构造函数、实例对象、原型对象之间额关系:
总结: