• javasccript进阶面向对象


    ES6是javascript的新版本,ES6就是ECMAScript6(6是版本号),又称ES2015

    <script>
            //创建类
            class star {
                //constructor函数,es6内部默认构造函数,可以接受传递过来的参数,同时返回实例对象
                constructor(uname) {
                    this.name = uname;
                }
                //类中添加方法
                sing(song) {
                    console.log(this.name + '会唱' + song);
    
                }
            }
            //利用类创建对象
            var ldh = new star("刘德华");
            console.log(ldh.name);
            //类里面所有的函数都不需要写function
            //类里面的函数间不可用逗号分隔
            ldh.sing('冰雨');
        </script>

    类的继承

    <script>
            //类的继承
            class Father {
                constructor() {
    
                }
                money() {
                    console.log(100);
    
                }
            }
            //使用extends即可让前面的类继承后面类的属性
            class child extends Father {
    
            }
            var son = new child();
            son.money();//100
        </script>

    但当遇到以下方法继承时情况会有所不同

    super关键字

    <script>
            class Father {
                constructor(x, y) {
                    this.x = x;
                    this.y = y;
                }
                sum() {
                    console.log(this.x + this.y);
    
                }
            }
            // var father = new Father(1, 2);
            // father.sum();
            //这里我出错的一点,将参数传入了sum的括号里,实际应该写进new Father()里
            class Son extends Father{
                constructor(x, y) {
                    this.x = x;
                    this.y = y;
                }
    
            }
            var son = new Son(1, 2);
            son.sum();//会报错
            //子类将父类的函数继承了过来,但是父类的sum()函数中的this指向的是父类,所以在父类中计算会出现错误
        </script>

    这个时候就要使用到super关键字,super关键字用于访问和调用对象父类上的函数,可以调用父类的构造函数,也可以调用父类的普通函数

    <script>
            class Father {
                constructor(x, y) {
                    this.x = x;
                    this.y = y;
                }
                sum() {
                    console.log(this.x + this.y);
    
                }
            }
            class Son extends Father {
                constructor(x, y) {
                    //super关键字用于访问和调用对象父类上的函数,可以调用父类的构造函数,也可以调用父类的普通函数。
                    super(x, y); //调用了父类中的构造函数
                }
            }
            var son = new Son(1, 2);
            son.sum(); //3
        </script>

     super关键字访问父类上的普通函数

    <script>
            class Father {
                say() {
                    return "我是爸爸";
                }
            }
            class Son extends Father {
                say() {
                    console.log("我是儿子");
    
                }
    
            }
            var son = new Son();
            son.say(); //输出 我是儿子
            //继承中,如果实例化子类输出一个方法,先看子类有无这个方法,再去看父类
        </script>

     super关键字调用父类普通函数的方法

    <script>
            class Father {
                say() {
                    return "我是爸爸";
                }
            }
            class Son extends Father {
                say() {
                    //super关键字调用父类普通函数的方法
                    console.log(super.say() + '的儿子');
                }
            }
            var son = new Son();
            son.say(); //输出 我是爸爸的儿子
        </script>

     子类继承父亲方法的同时扩展自己的方法

    <script>
            //子类继承父类方法的同时扩展自己的方法
            class Father {
                constructor(x, y) {
                    this.x = x;
                    this.y = y;
                }
                sum() {
                    console.log(this.x + this.y);
                }
            }
            class Son extends Father {
                constructor(x, y) {
                //注意:子类在构造函数中使用super,必须放到this前面(必须先调用父类的构造方法,再使用子类构造方法)
                    super(x, y);
                    this.x = x;
                    this.y = y;
                }
                //子类独有的减法运算
                subtract() {
                    console.log(this.x - this.y);
    
                }
            }
            var son = new Son(5, 3);
            son.subtract();
            son.sum();
        </script>

    使用类和对象时需要注意的问题

    <body>
        <button>点击</button>
        <script>
            //1.在ES6中类没有变量提升,所以必须先定义类,才能通过类实例化对象
            //2.类里面的共有属性和方法一定要加this使用
            //3.类里面的this指向问题
            //constructor里面的this指向实例对象,方法里面的this指向这个方法的调用者
            var that;
            class Father {
                constructor(uname) {
                    //在这里that指向的是constructor创建的实例化对象
                    that = this;
                    this.name = uname;
                    this.btn = document.querySelector('button');
                    this.btn.onclick = this.sing;
                }
                sing() {
                    //这个sing方法里面的this指向btn按钮,因为btn按钮调用了他
                    console.log(this); //<button>点击</button>
                    console.log("hi");
                    console.log(this.name); //undefined或者无输出 因为按钮里面无name属性
                    console.log(that.name); //小明
    
                }
            }
            var father = new Father('小明');
        </script>
    </body>

     类的概念是在ES6中才开始存在,ES6之前一直是使用构造函数和原型来模拟类的

    <script>
            //构造函数与原型
    
    
            //创建对象的方法
            //1.利用new Object()来创建对象
            var obj = new Object();
            //2.利用对象字面量来创建对象
            var obj = {};
            //3.利用构造函数来创建对象
            function Star(uname, age) {
                this.name = uname;
                this.age = age;
                this.sing = function () {
                    console.log('唱歌');
                }
            }
            var ldh = new Star('刘德华', 14);
            var zxy = new Star('张学友', 18);
            console.log(ldh);
            ldh.sing();
            //构造函数虽然好用,但是会存在浪费空间的问题
            console.log(ldh.sing === zxy.sing); //false,比较的是地址,而二者的复杂数据类型会分别开辟空间
            //为了节省空间,我们可以使用构造函数原型prototype
        </script>

    1.4构造函数原型prototype
    构造函数通过原型分配的函数是所有对象所共享的。
    JavaScript规定,每一个构造函数都有一个prototype属性,指向另-个对象。 注意这个prototype就是一
    个对象,这个对象的所有属性和方法,都会被构造函数所拥有。
    我们可以把那些不变的方法,直接定义在prototype对象上,这样所有对象的实例就可以共享这些方法。

    function Star(uname, age) {
                this.name = uname;
                this.age = age;
    
            }
            Star.prototype.sing = function () {
                console.log('我会唱歌');
            }
            var ldh = new Star('刘德华', 14);
            var zxy = new Star('张学友', 18);
            ldh.sing();
            zxy.sing();
            console.log(ldh.sing === zxy.sing);//true
            //一般情况下,我们的公共属性定义到构造函数里面,公共的方法我们放到原型对象身上

    对象原型_proto_

    对象都会有一个属性_proto_指向构造函数prototype原型对象,之所以我们对象可以使用构造函数prototype原型对象的属性和1方法,就是因为对象有_proto_原型的存在。

    对象原型(__proto__)和构造函数(prototype)原型对象里面都有一个属性constructor属性,constructor我们称为构造函数,因为它指向构造函数本身。

    constructor主要用于记录该对象引用于哪个构造函数,它可以让原型对象重新指向原来的构造函数。

    原型链

    1.9 JavaScript的成员查找机制(规则)
    ①当访问一一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性。
    ②如果没有就查找它的原型(也就是_ _proto_ 指向的prototype原型对象)。
    ③如果还没有就查找原型对象的原型( Object的原型对象)。
    ④依此类推一-直找到Object 为止( null)。
    ⑤_ proto_ 对象原型的意义就在 于为对象成员查找机制提供-个方向,或者说一条路线。

    <script>
            //原型对象的应用,可以扩展内置对象方法
            console.log(Array.prototype);
            //比如内置对象里面并没有求和函数,我们可以向里面添加一个
            Array.prototype.sum = function () {
                var sum = 0;
                for (var i = 0; i < this.length; i++) {
                    sum += this[i];
                }
                return sum;
            }
            //使用自己添加的函数
            var arr = [1, 2, 3];
            console.log(arr.sum());
        </script>

     call函数

    <script>
            // call可以调用函数,还可以修改函数运行时的this指向
            //call(指定的this指向,普通参数,普通参数,...)
            function fn() {
                console.log('美好的一天');
                console.log(this);
            }
            var o = {
                name: '123'
            };
            fn();
            fn.call();
            fn.call(o);
        </script>

    继承

    ES6之前并没有给我们提供extends继承,我们可以通过构造函数+原型对象模拟实现继承,被称为组合继承

    借用构造函数继承父类型属性

    核心原理:通过call()把父类型的this指向子类型的this,这样就可以实现子类型继承父类型的属性。

    <script>
            //借用父类构造函数继承属性
            //父类构造函数
            function Father(uname, age) {
                this.name = uname;
                this.age = age;
            }
            //子类构造函数
            function Child(uname, age) {
                //因为是在子类构造函数中,所以下面的this指向子类构造函数
                //即通过下面这一句我们将父类构造函数中的this指向了子类构造函数
                Father.call(this, uname, age);
            };
            var son = new Child('刘德华', 18);
            console.log(son);
        </script>

     借用构造函数继承父类型方法

    <script>
            //借用原型对象继承方法
            function Father(uname,age){
                this.name=uname,
                this.age=age
            }
            Father.prototype.money=function(){
                console.log(100000);
            }
            function Son(uname,age,score){
                Father.call(this,age,score);
                this.score=score;
            }
            Son.prototype=new Father();
            //如果利用对象的形式修改了原型函数,记得用constructor指回原来的原型对象
            Son.prototype.constructor=Son;
            //这个是子构造函数专门的方法
            Son.prototype.exam=function(){
                console.log('考试');
            }
            var son=new Son('刘德华',18,100);
            console.log(son);
            console.log(Father.prototype);
            console.log(Son.prototype.constructor);//Son的构造函数
            //如果上面没有用constructor指回原来的原型对象,上面输出结果将会是父类的构造函数
        </script>

     数组方法

    迭代(遍历方法):forEach(),map(),filter(),some(),every();

    forEach方法

    <script>
            //ES5中新增的一些方法
            //forEach
            var arr=[1,2,3];
            var sum=0;
            arr.forEach(function(value,index,array){
                //第一个参数为数组当前元素,第二个参数为数组当前索引,第三个参数为整个数组。
                console.log('当前元素'+value);
                console.log('当前索引'+index);
                console.log('当前数组'+array);
                sum+=value;
            });
            console.log(sum);
        </script>

    filter筛选数组方法

    <script>
            //filter筛选数组
            //arr.filter(function(value,index,array)),第一个参数是当前数组元素,第二个是数组序列,第三个是当前整个数组
            var arr = [1, 2, 3, 66, 88];
            var newarr = arr.filter(function (value, index) {
                return value >= 20;
            });
            console.log(newarr); //将数组中大于20的元素存入新数组newarr返回了回来
        </script>

    some查找指定元素方法

    some中的方法用于检测数组中的元素是否满足指定条件,即查找数组中是否有满足条件的元素

    some中的三个参数跟以上方法相同

    它的返回值是布尔值,如果查找到这个元素就返回true,反之返回false.

    如果找到第一个满足的的元素就会终止循环,不再查找。

    <script>
            //some方法
            var arr = [1, 5, 66, 88];
            var flag = arr.some(function (value) {
                return value > 20;
            });
            console.log(flag);
            var arr1 = ['pink', 'blue', 'skyblue'];
            var flag1 = arr1.some(function (value) {
                return value == 'pink';
            });
            console.log(flag1);
        </script>

    some方法与filter方法的比较

    filter也是查找满足条件的元素,但不同的是filter返回的是一个数组,而且是吧所有满足条件的元素返回出来。

    而some是查找满足条件的元素是否存在,返回的是一个布尔值,如果查找到第一个满足条件的元素就会终止循环

     trim()方法去除字符串两端空格

    此方法可以用于表单验证时去除用户输入的数据两端的空格

    // trim方法去除字符串两端空格
            var arr = '   andy ';
            console.log(arr);
            console.log(arr.trim());
            // 表单验证去除字符串两端空格
            var input = document.querySelector('input');
            var btn = document.querySelector('button');
            var div = document.querySelector('div');
            btn.onclick = function () {
                if (input.value.trim() === '') {
                    alert('请输入内容');
                } else {
                    console.log(input.value.trim());
                    console.log(input.value.trim().length);
                    div.innerHTML = input.value.trim();
                }
            }

     ES5中新增的方法

    Object.defineProperty()

    Object.defineProperty()定义对象中新属性或修改原有的属性

    Object.defineProperty(obj,prop,descriptor)

    obj:必需,目标对象

    prop:必需,需定义或修改的属性的名字

    descriptor:必需,目标属性所拥有的特性

    第三个参数descriptor说明:以对象形式{}书写

    value:设置属性的值,默认为undefined

    writable:值是否可以重写,true|false 默认为false

    enumerable:目标属性是否可以被枚举,true|false 默认为false

    configurable:目标属性是否可以被删除或是否可以再次修改特性true|false 默认为false

    函数的定义方式

    <script>
            //函数的定义方式
            //1.命名函数
            function fn() {}
            //2.匿名函数
            var fun = function () {}
            //3.利用new function('参数1','参数2','参数3')
            var f = new Function('a', 'b', 'console.log(a+b)');
            f(1, 2);
        </script>

     函数的调用方式

    <script>
            //函数的调用方式
            //1.普通函数
            function fn() {
                console.log('11');
            }
            //fn();  fn.call()
            //2.对象的方法
            var o={
                sayhi:function(){
                    console.log('喜欢你');
                }
            }
            //3.构造函数
            function Star(){
                console.log('喜欢你');
            }
            var o=new Star();
            //4.绑定事件函数
            btn.onclick=function(){};
            //5.定时器函数
            setInterval(function(){},1000);
            //6.立即执行函数
            (function(){})();//立即执行函数是自动调用的
        </script>

    函数内的this指向

     改变函数内部的this指向

    JavaScript为我们专门提供了一些函数方法来帮我们更优雅的处理函数内部this的指向问题,常用的有bind(),call(),apply()三种方法.

     高阶函数

    高阶函数是对其它函数进行的操作,它接收函数作为参数或将函数作为返回值输出

    函数也是一种数据类型,同样可以作为参数使用,最典型的就是回调函数。

    闭包:闭包指有权访问另一个函数作用域变量的函数

    <script>
          function fn(){
              var num=10;
              return function(){
                  console.log(num);
              }
          }
          var f=fn();
          f();//这样就实现了在函数外部访问函数内部的作用域变量
       </script>
    var lis=document.querySelectorAll('li');
         //点击li打印当前索引号
         for(var i=0;i<lis.length;i++){
             //立即执行函数
             (function(i){
                 lis[i].onclick=function(){
                     console.log(i);
                 }
             })(i);
         }
     //闭包应用-三秒钟之后,打印所有li元素的内容
        var lis=document.querySelectorAll('li');
        for(var i=0;i<lis.length;i++){
            (function(i){
                setTimeout(function(){
                    console.log(lis[i].innerHTML);
                    },3000)
            })(i);
        }

     利用递归遍历数据

    <script>
            //想要做的是输入id号,输出对应的数据
            //利用forEach遍历里面的每一个对象
            var data = [{
                id: 1,
                name: '家电',
                goods: [{
                    id: 11,
                    name: '电冰箱',
                    goods: [{
                        id: 111,
                        name: '海尔'
                    }, {
                        id: 112,
                        name: '美的'
                    }]
                }, {
                    id: 12,
                    name: '洗衣机'
                }]
            }, {
                id: 2,
                name: '服饰'
            }];
    
            function getID(json, id) {
                var o = [];
                json.forEach(function (item) {
                    if (item.id == id) {
                        o = item;
                        console.log(item);
                        //我们想要得到里层的数据11,12可以利用递归函数
                        //里面应该有goods这个数组,且数组长度不为0
                    } else if (item.goods && item.goods.length > 0) {
                        o = getID(item.goods, id);
                    }
                });
                return o;
            }
            getID(data, 1);
            getID(data, 11);
            getID(data, 111);
        </script>

     深拷贝的拷贝模式

    <script>
            //深拷贝的拷贝模式
            var obj = {
                id: 1,
                name: '11',
                msg: {
                    age: 18
                },
                arr: ['pink', 'red', 'black']
            }
            var o = {};
    
            function deepCopy(newobj, oldobj) {
                for (var k in oldobj) {
                    //判断我们的属性值属于哪种数据类型
                    //1.获取属性值 oldobj[k]
                    var item = oldobj[k];
                    if (item instanceof Array) {
                        //2.判断这个值是否是数组
                        newobj[k] = [];
                        deepCopy(newobj[k], item);
                    } else if (item instanceof Object) {
                        //3.判断这个值是否是对象
                        newobj[k] = {};
                        deepCopy(newobj[k], item);
                    } else {
                        //4.属于简单数据类型
                        newobj[k] = item;
                    }
                }
            }
            deepCopy(o, obj);
            console.log(o);
            o.msg.age = 20;
            console.log(obj);
        </script>

     正则表达式部分

    1.1什么是正则表达式
    正则表达式( Regular Expression )是用于匹配字符串中字符组合的模式。在JavaScript中,正则表达式也
    是对象。
    正则表通常被用来检索、替换那些符合某个模式(规则)的文本,例如验证表单:用户名表单只能输入英文字
    母、数字或者下划线,昵称输入框中可以输入中文(匹配)。此外,正则表达式还常用于过滤掉页面内容中的一
    些敏感词(替换) ,或从字符串中获取我们想要的特定部分(提取)等。

    正则表达式在js中的应用

    <script>
           //正则表达式在js中的使用
           //1.利用RegExp对象来创建正则表达式
           var regexp=new RegExp(/123/);
           console.log(regexp);
    
           //2.利用字面量创建正则表达式
           var rg=/123/;
           //3.test 方法用来检测字符串是否符合正则表达式要求的规范
           console.log(rg.test(123));
           console.log(rg.test('abc'));
       </script>

    表单验证案例

    <style>
            .right {
                color: green;
            }
    
            .wrong {
                color: red;
            }
        </style>
    </head>
    
    <body>
        <input type="text" class="uname"><span>请输入用户名</span>
        <script>
            var uname = document.querySelector('.uname');
            var span = document.querySelector("span");
            var rg = /^[a-zA-Z0-9-]{6,16}$/;
            uname.onblur = function () {
                if (rg.test(this.value)) {
                    span.className = 'right';
                    span.innerHTML = '输入格式正确';
                } else {
                    span.className = 'wrong';
                    span.innerHTML = '输入格式不正确';
                }
            }
        </script>
    </body>
  • 相关阅读:
    百度mp3地址解密码
    VB 在EXE后附加信息
    截屏函数
    Base64和StrToByte
    The Android ION memory allocator, DMABUF is mentioned as well
    DDC EDID 介绍
    Memory management for graphic processors TTM的由来
    科普 写display driver的必看 How video card works [2D的四种主要操作]
    GEM vs TTM
    DMABUF 背景介绍文章 Sharing buffers between devices
  • 原文地址:https://www.cnblogs.com/echol/p/13303792.html
Copyright © 2020-2023  润新知