JavaScript高级

JavaScript高级

1.面向对象编程

1.1.创建对象

  1. 通过Object()创建

    var person = new Object()
    person.name = 'Jack'
    person.age = 18
    person.sayName = function () {
      console.log(this.name)
    }
    
  2. 字面量来创建

    var person = {
      name: 'Jack',
      age: 18,
      sayName: function () {
        console.log(this.name)
      }
    }
    
  3. 工厂函数

    function createPerson (name, age) {
      return {
        name: name,
        age: age,
        sayName: function () {
          console.log(this.name)
        }
      }
    }
    //然后生成实例对象:
    var p1 = createPerson('Jack', 18)
    var p2 = createPerson('Mike', 18)
    
  4. 构造函数

function Person (name, age) {
  this.name = name
  this.age = age
  this.sayName = function () {
    console.log(this.name)
  }
}

var p1 = new Person('Jack', 18)
p1.sayName() // => Jack

var p2 = new Person('Mike', 23)
p2.sayName() // => Mike

1.2.构造函数

1.2.1.成员

实例成员:实例成员/对象成员(构造函数的this创建的属性) – 跟对象相关的成员,将来使用对象的方式来调用

静态成员:直接给构造函数添加的成员 – 静态成员不能使用对象的方式来调用(是构造函数私有的),静态成员使用构造函数来调用

1.2.2原型

在这里插入图片描述

  1. 创建构造函数就会有一个原型

  2. 访问原型

    a. Student.prototype

    可以用来设置属性和方法

    注意:

    ​ Student.prototype = {}

    ​ (1).先让原型重新指向一个对象

    ​ (2).然后再创建实例对象

    ​ (3).设置新对象的属性 constructor.Student

    b. 实例:__proto__(非标准属性,不要用它给原型设置属性或者方法)

    c. 属性:constructor(指向了创建p实例的构造函数)

    注意:对象的__proto__ 等于 构造函数的Student.prototype

  3. 原型链

    • 实例p.__proto__指向Student的原型
    • 实例p.__proto__.__proto__指向Object的原型
    • 实例p.__proto__``__proto__``__proto__指向null

1.3.属性的查找规则

实例对象p.name

​ 当调用对象的属性或者方法的时候,先去找对象本身的属性/方法 ,如果对象没有该属性或者方法。此时去调用原型中的属性/方法 ,原型中也没有该属性或者方法 ,去Object的原型里找,有就返回值,没有则找到null,返回underfined

1.4.属性的设置

直接在实例对象上设置,不会去原型里设置属性

2.继承

继承目的: 把子类型中共同的成员提取到父类型中,代码重用

2.1构造函数的原型方法继承:拷贝继承(for-in)

<script>
    var wjl = {
      name: '王健林',
      money: 10000000,
      cars: ['玛莎拉蒂', '特斯拉'],
      houses: ['别墅', '大别墅'],
      play: function () {
        console.log('打高尔夫');
      }
    }

    var wsc = {
      name: '王思聪'
    }

    // // 复制对象的成员给另一个对象
    // for (var key in wjl) {
    //   // 不给wsc复制同名的属性
    //   if (wsc[key]) {
    //     continue;
    //   }
    //   wsc[key] = wjl[key];
    // }

    // console.dir(wsc);

    // 对象的拷贝
    // 复制对象的成员给另一个对象
    function extend(parent, child) {
      for (var key in parent) {
        // 不给wsc复制同名的属性
        if (child[key]) {
          continue;
        }
        child[key] = parent[key];
      }
    }

    extend(wjl, wsc);

    console.dir(wsc);

/* //对象浅拷贝
        //Object.assign(新的对象,要复制的对象)
        var obj = {
            name: 'ls',
            age: 20,
            arr: [1, 2]
        }
        var newObj = Object.assign({}, obj);
        console.log(newObj); */

  </script>

深拷贝的方法

1.自己写for in 与递归

2.使用JSON.parse(JSON.stringify())

2.2另一种继承方式:原型继承

特点:能够让子类型创建的实例对象访问父原型里的方法

缺点:

  1. 创建子类实例时,无法向父类构造函数传参
  2. 来自原型对象的引用属性是所有实例共享的 ,一改变全改变
<script>
    // 继承:类型和类型之间的关系
    // 学生类型  老师类型  -> Person类型
    // 继承目的: 把子类型中共同的成员提取到父类型中,代码重用

    // 父类型
    function Person() {
      this.name = 'zs';
      this.age = 18;
      this.sex = '男';
    }

    // 子类型
    function Student() {
      this.score = 100;
    }

    Student.prototype = new Person();
    Student.prototype.constructor = Student;



    var s1 = new Student();
    console.log(s1.constructor);
    console.dir(s1);

    function Teacher() {
      this.salary = 3000;
    }

    // 原型继承: 无法设置构造函数的参数
  </script>

2.3构造函数的属性继承:借用构造函数

特点:子类型可以借用父类型的属性,或者实例成员

缺点:无法继承子类型的方法

继承属性,不继承方法

<script>
    // 借用构造函数
    // 父类型
    function Person(name, age, sex) {
      this.name = name;
      this.age = age;
      this.sex = sex;
      // this.sayHi
    }
    Person.prototype.sayHi = function () {
      console.log(this.name);
    }

    // 子类型
    function Student(name, age, sex, score) {
      Person.call(this, name, age, sex);
      this.score = score;
    }

    var s1 = new Student('zs', 18, '男', 100);
    console.dir(s1);

  </script>

2.4组合继承

组合继承:借用构造函数(属性) + 原型继承(方法)

<script>
        // 组合继承:借用构造函数 + 原型继承

        // 父类型
        function Person(name, age, sex) {
            this.name = name;
            this.age = age;
            this.sex = sex;
        }

        Person.prototype.sayHi = function() {
            console.log('大家好,我是' + this.name);
        }

        // 子类型
        function Student(name, age, sex, score) {
            // 借用构造函数
            Person.call(this, name, age, sex);

            this.score = score;
        }

        // 通过原型,让子类型,继承父类型中的方法
        Student.prototype = new Person();
        Student.prototype.constructor = Student;
        // 学生特有的方法
        Student.prototype.exam = function() {
            console.log('考试');
        }

        // var s1 = new Student('zs', 18, '男', 100);
        // console.dir(s1);


        // var p1 = new Person('ls', 18, '男');
        // console.dir(p1);


        function Teacher(name, age, sex, salary) {
            // 借用构造函数
            Person.call(this, name, age, sex);

            this.salary = salary;
        }

        // 通过原型让子类型继承父类型中的方法
        Teacher.prototype = new Person();
        Teacher.prototype.constructor = Teacher;

        var t1 = new Teacher('ww', 30, '男', 100000);
        console.dir(t1);

        t1.sayHi();
    </script>

3.函数进阶

1.函数声明

现代浏览器不会提升if语句中的函数声明 1.声明是函数 预解析会函数提升到最顶部function fn() {} 封装函数时用

2.函数表达式 预解析会把函数声明提升到最顶部 var fn = function() {} 注册事件时用

3.不要在条件语句中定义函数

4.函数也是对象 var fn = new Function(‘a’,‘b’,‘console.log(a+b)’); fn(1+2)

2.call、apply和bind

<script>
        // call  bind  apply 改变函数中的this

        // 函数是一个对象
        // var fn = new Function();
        // function fn() {
        // }

        // 证明fn是Function的实例(对象)
        // console.log(fn.__proto__ === Function.prototype);

        // console.dir(fn);

        function fn(x, y) {
            console.log(this);
            console.log(x + y);
        }

        // fn(5, 6); // this->window
        // call
        // 1 调用函数,改变函数中的this(临时改变)
        // 2 第一个参数 设置函数内部this的指向
        //   其它参数,对应函数的参数
        // 3 函数的返回值 call的返回值就是函数的返回值
        // 4 测试
        // var obj = {
        //     name: 'zs'
        // }
        // fn.call(obj, 5, 6);


        // apply 只有两个参数
        // 1 调用函数,改变函数中的this(临时改变)
        // 2 第一个参数  设置函数内部this的指向
        //   第二个参数  是数组
        // 3 函数的返回值 的返回值就是函数的返回值
        // 4 测试
        // var obj = {
        //   name: 'ls'
        // }
        // fn.apply(obj, [1, 2]);


        // bind 
        // 1 改变函数中的this(永久改变),不会调用函数,而是把函数复制一份
        // 2 第一个参数 设置函数内部this的指向
        //   其它参数,对应函数的参数
        // 3 函数的返回值 call的返回值就是函数的返回值
        // 4 测试
        var obj = {
            name: 'ww'
        }

        var f = fn.bind(obj, 5, 5);
        f();
    </script>

3.高阶函数

作为参数

function eat (callback) {
  setTimeout(function () {
    console.log('吃完了')
    callback()
  }, 1000)
}

eat(function () {
  console.log('去唱歌')
})

作为返回值

<script>
// 求两个数的和
    // 100 + m
    // 1000 + m
    // 10000 + m

    function getFun(n) {
      return function (m) {
        return n + m;
      }
    }

    // 求 100 + m
    var fn100 = getFun(100);
    // 求 1000 + m
    var fn1000 = getFun(1000);

    console.log(fn100(1));
    console.log(fn1000(1));
    
</script>

4.函数闭包

浏览器的垃圾回收机制:在函数调用完成之后,浏览器会周期性清除函数作用域内的变量,节省内存

闭包产生的背景:就是浏览器在函数执行完后,不再清空函数作用域内的变量

***什么是闭包:***在嵌套的函数内,里层的函数如果访问了外层函数内的变量,就会产生闭包

特点:返回一个函数,引用外部的变量

优点:延展函数作用域

缺点:内存溢出

5.函数递归

递归:函数自己调用自己,一定要有一个结束条件

在递归的过程中会出错

内容溢出:超过了最大的堆栈大小

递归一般都要写一个结束的条件

<script>
    // n的阶乘
    // 1 * 2 * 3....* n

    // n = 3,  3 * fn(3 - 1)
    // n = 2,  2 * fn(2 - 1)
    // n = 1,  1
    function fn(n) {
      if (n === 1) {
        return 1;
      }
      return n * fn(n - 1);
    }
    console.log(fn(3));
    console.log(fn(4));
    
  </script>
<script>
    // 斐波那契数列 1、1、2、3、5、8、13、21、34、.....
    
    function fn(n) {
      if (n === 1 || n === 2) {
        return 1;
      }
      return fn(n - 1) + fn(n - 2);
    }

    console.log(fn(3));
    console.log(fn(5));
    
  </script>

深拷贝

利用递归

<script>
        var obj1 = {
            name: 'zs',
            age: 18,
            sex: '男',
            dog: {
                name: '金毛',
                age: 2,
                yellow: '黄色'
            },
            friends: ['lilei', 'hanmeimei']
        }

        var obj2 = {};


        var arr = [];
        console.log(arr instanceof Array);
        console.log(arr instanceof Object);

        function deepCopy(o1, o2) {
            for (var key in o1) {
                if (o1[key] instanceof Array) {

                    o2[key] = [];
                    deepCopy(o1[key], o2[key]);
                } else if (o1[key] instanceof Object) {
                    o2[key] = {};
                    deepCopy(o1[key], o2[key]);
                } else {
                    o2[key] = o1[key];
                }
            }
        }
        deepCopy(obj1, obj2);
        obj1.name = 'xxxx';
        obj1.dog.name = '大黄';
        obj1.friends[0] = 'xxxx';

        console.dir(obj1);
        console.dir(obj2);
</script>

es6方法

<script>
var obj1 = {
            name: 'zs',
            age: 18,
            sex: '男',
            dog: {
                name: '金毛',
                age: 2,
                yellow: '黄色'
            },
            friends: ['lilei', 'hanmeimei']
        }
        var newObj = JSON.parse(JSON.stringify(obj1));
    </script>

4.正则表达式

正则表达式的作用
  1. 能对我们想要的字符串进行匹配
  2. 能对我们想要的字符串进行提取
  3. 能对我们想要的字符串进行替换

4.1元字符

常用元字符

元字符说明
\d匹配数字
\D匹配任意非数字的字符
\w匹配字母或数字或下划线
\W匹配任意不是字母,数字,下划线
\s匹配任意的空白符
\S匹配任意不是空白符的字符
.匹配除换行符以外的任意单个字符
^表示匹配行首的文本(以谁开始)
$表示匹配行尾的文本(以谁结束)

限定符

限定符说明
*重复零次或更多次
+重复一次或更多次
重复零次或一次
{n}重复n次
{n,}重复n次或更多次
{n,m}重复n到m次

其他

[] 字符串用中括号括起来,表示匹配其中的任一字符,相当于或的意思
[^] 匹配除中括号以内的内容
\ 转义符
| 或者,选择两者中的一个。注意|将左右两边分为两部分,而不管左右两边有多长多乱
() 从两个直接量中选择一个,分组
eg:gr(a|e)y匹配gray和grey
[\u4e00-\u9fa5] 匹配汉字

/1{2,4}$/, ‘请输入2-4个汉字’

案例

验证手机号:

^\d{11}$

验证邮编:

^\d{6}$

验证日期:2019-6-8

^\d{4}-\d{1,2}-\d{1,2}$

验证邮箱:xxx@itcast.cn:

^\w+@\w+\.\w+$

验证IP地址 192.168.1.10

^\d{1,3}\(.\d{1,3}){3}$

4.2JavaScript 中使用正则表达式

创建正则对象

方式一

// 正则匹配
var str = 'abc';
var reg = new RegExp('\\w+'); //在这种方式写\d \w \s 加上转义符
console.log(reg.test(str)); //有一个返回值 是boolean

方式二

// 正则匹配 正则对象test方法
var str = 'abc';
var reg1 = /\w+/;
console.log(reg.test(str));//有一个返回值 是boolean

参数

标志说明
i忽略大小写
g全局匹配
gi或者ig全局匹配+忽略大小写

案列(表单验证)

<body>
    QQ号:<input type="text" id="txtQQ"><span></span><br>
    邮箱:<input type="text" id="txtEMail"><span></span><br>
    手机:<input type="text" id="txtPhone" ><span></span><br>
    生日:<input type="text" id="txtBirthday"><span></span><br>
    姓名:<input type="text" id="txtName"><span></span><br>

    <script>
      // 1 验证QQ号
      var txtQQ = document.getElementById('txtQQ');
      // 当光标离开文本框的时候
      txtQQ.onblur = function () {
        // 验证用户的输入是否是QQ号
        var reg = /^\d{5,12}$/;
        var span = this.nextElementSibling;
        // 检测用户输入的文本是否匹配指定的模式(正则表达式)
        if (!reg.test(this.value)) {
          // 不匹配  在文本框后面的span中进行相应的提示
          span.innerText = '请输入正确的QQ格式';
          span.style.color = 'red';
        } else {
          // 匹配
          span.innerText = '';
          span.style.color = '';
        }
      }

      // 2 验证邮箱
      var txtEMail = document.getElementById('txtEMail');
      txtEMail.onblur = function () {
        // 验证用户的输入是否是邮箱地址  xxx@itcast.com.cn
        var reg = /^\w+@\w+(\.\w+)+$/;
        var span = this.nextElementSibling;
        // 验证
        if (!reg.test(this.value)) {
          span.innerText = '请输入正确的电子邮箱格式';
          span.style.color = 'red';
        } else {
          // 匹配
          span.innerText = '';
          span.style.color = '';
        }
      }
      
      
      //表单验证封装
      /* // 1 验证QQ号
      addCheck('txtQQ', /^\d{5,12}$/, '请输入正确的QQ号格式');
      // 2 验证电子邮箱
      addCheck('txtEMail', /^\w+@\w+(\.\w+)+$/, '请输入正确的EMail号格式');
      // 3 手机号
      addCheck('txtPhone', /^[1-9]\d{10}$/, '请输入正确的手机号码格式');
      // 4 验证日期
      addCheck('txtBirthday', /^\d{4}-\d{1,2}-\d{1,2}$/, '请输入正确的日期格式')
      // 5 验证姓名
      addCheck('txtName', /^[\u4e00-\u9fa5]{2,4}$/, '请输入2-4个汉字')

      // 文本框的验证封装成一个函数
      // 第一个参数是元素的id
      // 第二个参数 正则表达式对象 RegExp
      // 第三个参数 是提示的文本
      function addCheck(elementId, reg, tip) {
        var element = document.getElementById(elementId);
        element.onblur = function () {
          var span = this.nextElementSibling;
          // 验证
          if (!reg.test(this.value)) {
            span.innerText = tip;
            span.style.color = 'red';
          } else {
            span.innerText = '';
            span.style.color = '';
          }
        }
      } */
    </script>
</body>

4.3正则表达式的相关方法

1.RegExp对象

test() 匹配 返回值是是boolean,(true/false)

exec() 提取 提取一个内容;只返回一个匹配到的结果 如果没有匹配的内容返回null

2. String对象

match() 提取 可以提取多个内容

replace() 替换

split() 切割 变为数组

search() 搜索

4.4正则提取

<script>
        // 1. 提取工资
        var str = '张三:1000,李四:5000,王五:8000。';
        var reg = /\d+/g;
        // 提取多个内容
        console.log(str.match(reg));




        // 2. 提取email地址
        var str = '123123@xx.com,fangfang@valuedopinions.cn 这是其它内容 286669312@qq.com 2、emailenglish@emailenglish.englishtown.com 286669312@qq.com...';

        var reg = /\w+@\w+(\.\w+)+/g;

        console.log(str.match(reg));


        // 3. 分组提取  
        // 3. 提取日期中的年部分  2015-5-10
        var dateStr = '2015-1-5';
        var reg = /(\d{4})-(\d{1,2})-(\d{1,2})/;

        // reg.test(dateStr);

        // reg.exec(dateStr);
        console.log(reg.exec(dateStr));

        dateStr.match(reg);

        console.log(RegExp.$1);
        console.log(RegExp.$2);
        console.log(RegExp.$3);




        // 4. 提取邮件中的每一部分
        var str = 'xxxx@itcast.com';
        var reg = /(\w+)@(\w+)\.(\w+)/;
        reg.test(str);
        console.log(reg.test(str));

        console.log(RegExp.$1);
        console.log(RegExp.$2);
        console.log(RegExp.$3);
    </script>

split

<script>
        // 1. 提取日期中的年部分  2015-5-10
        var dateStr = '2015-1-5';
        console.log(dateStr.split('-'));

        // var dateStr = '2015/1-5';
        // console.log(dateStr.split(/[/-]/));


        // 2. 提取邮件中的每一部分
        var str = 'xxxx@itcast.com';
        console.log(str.split(/[@\.]/));
    </script>

4.5正则替换

<script>
        // 1. 替换所有空白
        var str = "   123AD  asadf     asadfasf  adf ";
        // trim() 去除前后的空格
        // console.log( str.trim());
        // replace() 只能替换掉第一个查找到的内容
        // console.log(str.replace(' ', 'x'));
        // console.log(str.replace(/\s/g, ''));
        // console.log(str.split(' ').join(''));
        
        
        
        console.log(str.replace(/\s/g, ''));
        console.log(str.split(' '));
        console.log(str.split(' ').join(''));

        // 2. 把所有,和,替换为.
        var str = "abc,efg,123,abc,123,a";

        console.log(str.replace(/,|,/g, '.'));
        console.log(str.replace(/[,,]/g, '.'));
    </script>
teStr.split(/[/-]/));


        // 2. 提取邮件中的每一部分
        var str = 'xxxx@itcast.com';
        console.log(str.split(/[@\.]/));
    </script>

4.5正则替换

<script>
        // 1. 替换所有空白
        var str = "   123AD  asadf     asadfasf  adf ";
        // trim() 去除前后的空格
        // console.log( str.trim());
        // replace() 只能替换掉第一个查找到的内容
        // console.log(str.replace(' ', 'x'));
        // console.log(str.replace(/\s/g, ''));
        // console.log(str.split(' ').join(''));
        
        
        
        console.log(str.replace(/\s/g, ''));
        console.log(str.split(' '));
        console.log(str.split(' ').join(''));

        // 2. 把所有,和,替换为.
        var str = "abc,efg,123,abc,123,a";

        console.log(str.replace(/,|,/g, '.'));
        console.log(str.replace(/[,,]/g, '.'));
    </script>

  1. \u4e00-\u9fa5 ↩︎

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值