前言: 

    今天和大家分享一下近期整理的有关JavaScriptOOP的基础知识~~~我们一起来学习一下……

***本章关键词:JavaScriptOOP的入门基础,成员属性,成员方法,原型与原型链……

 

一、JavaScriptOOP基础

一、面向对象编程OOP
1、语言的分类:
面向机器:汇编语言
面向过程:C语言
面向对象:C++,Java,PHP等
2、面向过程和面向对象
①面向过程:专注于如何去解决一个问题的过程。
编程特点:用一个个函数去实现过程操作,没有类和对象的概念;
②面向对象:专注于有哪一个对象实体去解决这个问题。
编程特点是:出现了一个个的类,由类去生成对象。

二、面向对象的三大特征
继承,封装,多态

三、类&对象的关系
1、类:一群有相同特征(属性)和行为(方法)的集合
eg: 人类
属性:"身高,体重,年龄"
方法:"吃饭,睡觉,敲代码"

2、对象:从类中,new出的具有确定属性值和方法的个体称为对象。
eg:张三:属性:身高:身高178,体重150 方法:说话---我叫张三

3、类和对象的关系:
类是抽象的,对象是具体的。
!类是对象的抽象化,对象是类的具体化!

通俗的来讲:
类是一个抽象概念,表示具有相同属性和行为的集合。
但是类仅仅表示表明这类群体具有相同的属性,但是没有具体的属性值。
而对象是对类的属性进行具体赋值后,而得到的一个具体的个体;

eg:人类有身高体重年龄,但不能具体说人类的身高体重具体是多少;而张三是人类的一个具体个体,身高体重等有具体值,则张三就是人类的一个对象。

4、使用类和对象的步骤:
①创建一个类(构造函数):
类名,必须要每个单词首字母都大写


function 类名(属性一){
this.属性 = 属性一;
this.方法= function(){}
//this指向谁?即将调用当前构造函数的对象。
}


②通过类,实例化出一个新的对象;


var obj = new 类名(属性一Value);
//原构造函数中this,指向新创建的obj对象
obj.方法();调用方法
obj.属性();调用属性
实例化对象的时候,会执行构造函数

5、两个重要属性:
constructor:返回当前对象的构造函数。(只有对象才有,返回的是构造函数-类)
>>>zhangsan.constructor == Person
>>>对象的constructor,位于_proto_原型对象上(后续讲解)

instanceof:判断对象是否是某个类的实例
>>>zhangsan instanceof Person true
>>>zhangsan instanceof Object true
>>>Person instanceof Object true(函数也是对象)

6、广义对象与狭义对象:
广义对象:除了用字面量声明的基本数据类型之外,外物皆对象,换句话说,能够添加属性和方法的变量,就是对象;
var s = "1" ; 不是对象
var s = new String("1") ; 就是对象
狭义对象:只有属性,方法,除此之外没有任何东西。
var obj = {}; var obj = new Object();

 

二、成员属性与成员方法

一、成员属性与成员方法
1、在构造函数中通过this.属性声明;或者实例化出对象后,通过"对象.属性"追加的。
都属于成员属性,或成员方法;也叫实例属性与实例方法。

成员属性/方法,是属于实例化出的这个对象。
通过"对象.属性"调用

二、静态属性与静态方法
2、通过"类名.属性名","类名.方法名"声明的变量,称为静态属性,静态方法;也叫类属性、类方法。

类属性/类方法,是属于类的(属于构造函数的)
通过"类名.属性名"调用

3、成员属性,是属于实例化出的对象的,会出现在新对象的属性上
静态属性,是属于类(构造函数)自己的,不会出现在新对象的属性上

4、JS对象属性的删除:
①对象无需手动删除,JS
②删除对象的属性:delete 对象名.属性名

5、对象是引用数据类型
也就是说,当new出一个对象时,这个obj变量存储的实际上是对象的地址,在对象赋值时,赋的也是地址。
function Person(){}
var xiaoxi = new Person();//xiaoxi对象实际上存的是地址
var ashu = xiaoxi;//赋值时,实际是将xiaoxi存的地址给了ashu
ashu.name = "阿树";//阿树通过地址,修改了地址
console.log(xiaoxi.name);//xiaoxi再通过地址打开对象,实际已经变了

引用数据类型,赋值时传递的是引用(地址)---快捷方式
基本数据类型,赋值时传递的是数据(值)

三、私有属性和私有方法
6、在构造函数中,通过var声明的属性,成为私有属性:
function Person(){var num=1;}

私有属性的作用域,仅在当前函数有效。对外不公开,即通过对象/类都无法调用到。

 

三、原型与原型链

【__proto__与prototype】
1、prototype(函数的原型):函数才有prototype。
prototype是一个对象,指向了当前构造函数的引用地址。
2、__proto__(对象的原型对象):所有对象都有__proto__属性。当用构造函数实例化(new)一个对象时,
会将新对象的__proto__属性,指向构造函数的prototype。

eg:zhangsan.__proto__==Person.prototype √

所有对象最终都会指向Object()的prototype。

【原型链】
1、通过构造函数,new出的对象,新对象的__proto__指向构造函数的prototype。
2、所有函数的__proto__指向Function()的prototype。
3、非构造函数new出的对象({} new Object() 对象的prototype)的__proto__指向Object的prototype。
4、Object的__proto__指向Null。

 

四、原型属性与原型方法

【类中属性与方法的声明方式】
1、成员属性、成员方法:
this.name = ""; this.func = function(){}
>>>属于实例化出的对象的。通过"对象.属性"调用。

2、静态属性、静态方法:
Person.name = ""; Person.func = function(){}
>>>属于类(构造函数)的。通过"类名.属性"调用。

3、私有属性、私有方法:
在构造函数中,使用var num = 1;声明
>>>只在构造函数内部能用,在外部无法通过任何方式访问。

4、原型属性、原型方法:
Person.prototype.name = "";
Person.prototype.func = function(){};
>>>写在了构造函数的prototype上,当使用构造函数实例化对象时,该属性方法会进入新对象的__proto__上。

也就是说,1/4使用对象可访问,2使用类名可访问,3只能在函数的{}内使用。

5、习惯上,我们会将属性写为成员属性,而方法写为原型方法;

eg:

1 function Person(){
2 this.name = "zhangsan";
3 }
4 Person.prototype.say = function(){}

 

原因:
①实例化出对象后,所有属性直接在对象上,所有方法都在__proto__上,非常直观清晰。
②方法写到prototype上,要更加节省内存。
③使用for in 循环时,会将对象以及对象原型链上的所有属性和方法打印出来,而方法往往是不需要展示的。
将方法写到__proto__上,可以使用hasOwnProperty将原型上的方法更好的过滤。
④官方都这么写。

6、当访问对象的属性/方法时,会优先使用对象自有的属性和方法。
如果没有找到,便使用__proto__属性在原型上查找,如果找到即可使用。
但是,当对象自身,以及__proto__上有同名方法,执行对象自身的。

7、可以通过prototype扩展内置函数的相关方法。

代码演示:

 1 function Person(){
 2 this.name1 = "name1"; //成员属性
 3 this.age = "age1";
 4 this.sex = "男";
 5 this.say = function(){
 6 alert("我是大帅哥!");
 7 }
 8 var name2 = "name2";//私有属性
 9 }
10 Person.name3 = "name3";//静态属性
11 Person.prototype.name4 = "name4";//原型属性
12 
13 
14 Person.prototype.say = function(){
15 alert("我叫"+this.name1);
16 }
17 
18 var zhangsan = new Person();
19 //    zhangsan.say = function(){
20 //    alert("我是大帅哥!");
21 //    }
22 zhangsan.say();
23 zhangsan.toString();
24 
25 console.log(zhangsan);
26 
27 //    console.log(zhangsan.name1);
28 //    console.log(zhangsan.name2);
29 //    console.log(zhangsan.name3);
30 //    console.log(zhangsan.name4);
31 //    
32 //    console.log(s);

 

可以通过prototype扩展内置函数的相关方法

代码演示:

 1 Number.prototype.add = function(a){
 2 return this+a
 3 }
 4 
 5 var num = new Number(10);
 6 console.log(num);
 7 alert(num.add(3));
 8 
 9 /*
10 * 为Array类添加一个find(val)方法,当一个Array对象调用该方法的时候,如果能找到val值,则返回其下标,否则返回-1。
11 */
12 Array.prototype.find = function(val){
13 for (var i = 0; i<this.length;i++) {
14 if(this[i]==val){
15 return i;
16 }
17 }
18 return -1;
19 }
20 var arr = new Array(1,2,3,4,5);
21 alert(arr.find(1));

 



位String类添加一个字符串反转方法

 1 String.prototype.fanzhuan = function(){
 2 var arr = this.split("");
 3 arr.reverse();
 4 return arr.join("")
 5 }
 6 
 7 
 8 console.log(str.fanzhuan());
 9 
10  
11 
12 for-in循环
13 
14 
15for-in循环】
16 for-in循环,主要用于遍历对象。
17 for()中格式:for(keys in obj){}
18 
19 keys表示obj对象的每一个键值对的键,所以{}中,使用obj[keys]读取每个值;
20 但是,使用for-in循环,不但能遍历对象本身的属性和方法。还能够遍历对象原型链上的所有属性和方法。
21 
22 可以使用hasOwnProperty判断一个属性,是否是对象自身的属性。
23 obj.hasOwnProperty(keys)==true 表示:keys是对象自身的一个属性
24 
25 代码演示:
26 // foreach
27 function Person(){
28 this.name1 = "name11111"; //成员属性
29 this.age = "age11111";
30 this.func2 = function(){
31 console.log("thisFun")
32 }
33 }
34 Person.name3 = "name333333";
35 Person.prototype.name4 = "name44444";
36 Person.prototype.func1 = function(){
37 console.log("prototypeFun")
38 }
39 var zhangsan = new Person();
40 for(keys in zhangsan){
41 if(zhangsan.hasOwnProperty(keys)){ //过滤掉原型上的属性,只打印对象自身属性
42 console.log(zhangsan[keys])
43 }
44 }

 

五、JS OOP中的继承(JS模式实现继承的三种方式)

【文档注释】第一行两个星号
/**
* ……
*/
调用函数时,可以看到注释内容

【JS OOP 中的继承】
1、使用一个子类继承另一个父类,子类可以自动拥有父类的属性和方法。

>>>继承的两方,发生在两个类之间。

2、JS模式实现继承的三种方式:

1)扩展Object实现继承

①定义父类:function Parent(){}
②定义子类:function Son(){}
③通过原型给Object对象添加一个扩展方法。

1 Object.prototype.customExtend = function(parObj){
2 for(var i in parObj){
3 //通过for-in循环,把父类的所有属性方法,赋值给自己。
4 this[i] = ParObj[i];
5 }
6 }

 

④子类对象调用扩展方法
son.customExtend(Parent);

2)使用call和apply
首先,了解一下call和apply:通过函数名调用方法,强行将函数中的this指向某个对象;
call写法:func.call(func的this指向的obj,参数1,参数2...);
apply写法:func.apply(func的this指向的obj,[参数1,参数2...]);
call与apply的唯一区别:在于接收func函数的参数方式不同。call采用直接写多个参数的方式,而apply采用是一个数组封装所有参数。
①定义父类 funtion Parent(){}
②定义子类 function Son(){}
③在子类中通过call方法或者apply方法去调用父类。
function Son(){
Parent.call(this,....);
}
3)使用原型继承
①定义父类function Parent(){}
②定义子类function Son(){}
③把在子类对象的原型对象声明为父类的实例。
Son.prototype = new Parent();

 

六、闭包

【JS中的作用域】

1、全局变量:函数外声明的变量
局部变量:函数内声明的变量

在JS中,函数为唯一的局部作用域,而if、for等其他{}没有自己的作用域
所以,函数外不能访问局部变量。
其实,变量在函数执行完毕以后,占用的内存就被释放。

2、如何访问函数私有变量?
JS中,提供了一种"闭包"的概念:在函数内部,定义一个子函数,可以用子函数访问父函数的私有变量。执行完操作以后,将子函数通过return返回。

 1 function func2(){
 2 var num = 1;
 3 function func3(){
 4 var sum = num+10;
 5 alert(sum);
 6 }
 7 return func3;
 8 }
 9 var f = func2();
10 f();

 

3、闭包的作用:
① 访问函数的私有变量;
② 让函数的变量始终存在于内存中,而不被释放。


代码演示:

 1 function func1(){
 2 var n = 1;
 3 }
 4 if(true){
 5 var m = 3;
 6 }
 7 //alert(m); // 3
 8 func1();
 9 //alert(n);// 报错。函数外不能访问局部变量。其实,n变量在func1函数执行完毕以后,占用的内存就被释放。
10 
11 
12 /*闭包*/
13 function func2(){
14 var num = 1;
15 function func3(){
16 var sum = num+10;
17 alert(sum);
18 }
19 return func3;
20 }
21 var f = func2();
22 f();
23 
24 // 循环转一次,创建一个lis[i].onclick函数。但是,当点击li执行函数的时候,i已经变为6,所以无论点击哪一个,i都是6
25 // 循环创建lis[i].onclick的时候, 循环一次,li[i]里面的i都被赋为不同值;创建了 li[1] li[2] li[3]...
26 // 但是,创建过程中,并没有执行onlick后面的函数,所以函数里面的i并没有赋值,还是字母i。
27 // 最终,我们点击li[1] li[2]...时,onclick函数里面的i才会赋值。(但此时,全局变量的i ,已经成为6 了)
28 var lis = document.getElementsByTagName("li");
29 for (var i=0;i<lis.length;i++) {
30 lis[i].onclick = function(){
31 //alert("您/点击了第"+i+"个li!");
32 //console.log(lis[i]);
33 //console.log(this);
34 }
35 }
36 
37 // 循环转一次,创建一个自执行函数。
38 // 而自执行函数拥有自己的作用域,所以用函数局部作用域j保存当前的全局变量i值。这样,创建第一个自执行函数,它的j=1;创建第二个,它的j=2...不同函数的j互不干扰。
39 // 这样,循环转完以后,相当于创建了6个自执行函数,每个函数中都有一个不同的j变量
40 var lis = document.getElementsByTagName("li");
41 for (var i=0;i<lis.length;i++) {
42 !function(){
43 var j = i;
44 lis[j].onclick = function(){
45 alert("您/点击了第"+j+"个li!");
46 //console.log(lis[i]);
47 //console.log(this);
48 }
49 }();
50 }
51 
52 var lis = document.getElementsByTagName("li");
53 for (var i=0;i<lis.length;i++) {
54 !function(j){
55 lis[j].onclick = function(){
56 alert("您/点击了第"+j+"个li!");
57 //console.log(lis[i]);
58 //console.log(this);
59 }
60 }(i);
61 }

 

 

..。..。..。..。..。..。..。..。..。END..。..。..。..。..。..。..。..。..。

..。..。..。..。..。..。希望可以帮到你哟..。..。..。..。..。..。


 

作者:夕照希望
出处:http://www.cnblogs.com/hope666/  
posted on 2017-05-14 23:52  夕照希望  阅读(1287)  评论(1编辑  收藏  举报