• 【JavaScript OPP基础】---新手必备


    前言: 

        今天和大家分享一下近期整理的有关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/  
    今日事,今日毕!我爱敲代码,代码使我快乐~
  • 相关阅读:
    smarty语法
    combobox里面显示checkbox
    requirejs打包项目
    datagrid中用tooltip
    combobox默认值为第一个数据,修改为空值
    easyui-textbox高为0
    C++并发编程 异步任务
    C++并发编程 互斥和同步
    C++并发编程 thread
    C++智能指针
  • 原文地址:https://www.cnblogs.com/hope666/p/6854443.html
Copyright © 2020-2023  润新知