JavaScript高级(2)

JavaScript高级(2)

函数的其他成员

  • arguments
    • 实参集合
  • caller
    • 函数的调用者
  • length
    • 形参的个数
  • name
    • 函数的名称
function fn(x, y, z) {
  console.log(fn.length) // => 形参的个数
  console.log(arguments) // 伪数组实参参数集合
  console.log(arguments.callee === fn) // 函数本身
  console.log(fn.caller) // 函数的调用者
  console.log(fn.name) // => 函数的名字
}

function f() {
  fn(10, 20, 30)
}

f()

高阶函数

  • 函数可以作为参数
  • 函数可以作为返回值

作为参数

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

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

作为返回值

function genFun (type) {
  return function (obj) {
    return Object.prototype.toString.call(obj) === type
  }
}

var isArray = genFun('[object Array]')
var isObject = genFun('[object Object]')

console.log(isArray([])) // => true
console.log(isArray({})) // => true

函数闭包

function fn () {
  var count = 0
  return {
    getCount: function () {
      console.log(count)
    },
    setCount: function () {
      count++
    }
  }
}

var fns = fn()

fns.getCount() // => 0
fns.setCount()
fns.getCount() // => 1

作用域、作用域链、预解析

  • 全局作用域
  • 函数作用域
  • 没有块级作用域
{
  var foo = 'bar'
}

console.log(foo)

if (true) {
  var a = 123
}
console.log(a)

作用域链示例代码:

var a = 10

function fn () {
  var b = 20

  function fn1 () {
    var c = 30
    console.log(a + b + c)
  }

  function fn2 () {
    var d = 40
    console.log(c + d)
  }

  fn1()
  fn2()
}
  • 内层作用域可以访问外层作用域,反之不行。

闭包

闭包就是能够读取其他函数内部变量的函数,
由于在JavaScript语言中,只有函数内部的子函数才能读取局部变量,
由此可以把闭包简单成“定义在一个函数内部的函数”。
所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

闭包的用途

  • 可以在函数外部读取函数内部成员
  • 让函数内成员始终存活在内存中

一些关于闭包的例子

var arr = [10, 20, 30]
for(var i = 0; i < arr.length; i++) {
  arr[i] = function () {
    console.log(i)
  }
}

函数递归

递归执行模型

function fn1 () {
  console.log(111)
  fn2()
  console.log('fn1')
}

function fn2 () {
  console.log(222)
  fn3()
  console.log('fn2')
}

function fn3 () {
  console.log(333)
  fn4()
  console.log('fn3')
}

function fn4 () {
  console.log(444)
  console.log('fn4')
}

fn1()

计算阶乘的递归函数

function factorial (num) {
  if (num <= 1) {
    return 1
  } else {
    return num * factorial(num - 1)
  }
}

递归应用场景

  • 深拷贝

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <script>
    // 深拷贝
    var obj1 = {
      name: 'zs',
      age: 18,
      sex: '男',
      dog: {
        name: '金毛',
        age: 2
      },
      friends: ['ls', 'ww']
    }

    // 深拷贝  把o1的成员拷贝给o2
    function deepCopy(o1, o2) {
      for (var key in o1) {
        // 获取key属性对应的值
        var item = o1[key];

        // 如果item 是对象?
        // var o = {}
        if (item instanceof Object) {
          // var o = {};
          o2[key] = {}; 
          deepCopy(item, o2[key]);
        } else if (item instanceof Array) {
          // 如果item 是数组呢?
          // var arr = [];
          o2[key] = [];
          deepCopy(item, o2[key]);
        } else {
          // 如果是简单类型
          o2[key] = o1[key];
        }
      }
    }


    var obj2 = {};

    deepCopy(obj1, obj2);

    // 修改obj1中的成员 是否会影响obj2?
    obj1.dog.name = 'xxx';
    obj1.friends[0] = 'xxx';

    console.dir(obj2);
  </script>
</body>
</html>
  • 遍历DOM树

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>遍历DOM树</title>
</head>
<body>
  <h1>遍历 DOM 树</h1>
  <p style="color: green;">Tip: 可以在遍历的回调函数中任意定制需求</p>
  <div>
    <ul id="list">
      <li>123</li>
      <li>456</li>
      <li>789</li>
    </ul>
    <div>
      <div>
        <span>haha</span>
      </div>
    </div>
  </div>
  <div id="demo_node">
    <ul>
      <li>123</li>
    </ul>
    <p>hello</p>
    <h2>world</h2>
    <div>
      <p>dsa</p>
      <h3>
        <span>dsads</span>
      </h3>
    </div>
  </div>
  <script>
    // 遍历指定元素下所有的子元素
    function loadTree(parent, callback) {
      for (var i = 0; i < parent.children.length; i++) {
        // 遍历第一级子元素
        var child = parent.children[i];
        // console.log(child);
        if (callback) {
          // 处理找到的子元素
          callback(child);
        }

        // 递归调用
        loadTree(child);
      }
    }

    var ul = document.getElementById('list');
    loadTree(ul, function (element) {
      element.onclick = function () {
        console.log(this.innerText);
      }
    });
  </script>
</body>
</html>

正则表达式

  • 了解正则表达式基本语法
  • 能够使用JavaScript的正则对象

正则表达式简介

正则表达式的作用

1.给定的字符串是否符合正则表达式的过滤逻辑(匹配)
2.可以通过正则表达式,从字符串中获取我们想要的特定部分(提取)
3.强大的字符串替换能力(替换)

正则表达式的特点

1.灵活性、逻辑性和功能性非常的强
2.可以迅速地用极简单的方式达到字符串的复杂控制
3.对于刚接触的人来说,比较晦涩难懂

正则表达式的测试

在线测试正则

正则表达式的组成

  • 普通字符abc 123
  • 特殊字符(元字符):正则表达式中有特殊意义的字符\d \w

常用元字符

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

限定符

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

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

验证手机号:

^\d{11}$

验证邮编:

^\d{6}$

验证日期 2012-5-01

^\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}$

JavaScript 中使用正则表达式

创建正则对象

方式1:

var reg = new RegExp('\d', 'i');
var reg = new RegExp('\d', 'gi');

方式2:

var reg = /\d/i;
var reg = /\d/gi;

参数

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

正则匹配

// 匹配日期
var dateStr = '2015-10-10';
var reg = /^\d{4}-\d{1,2}-\d{1,2}$/
console.log(reg.test(dateStr));

正则提取

// 1. 提取工资
var str = "张三:1000,李四:5000,王五:8000。";
var array = str.match(/\d+/g);
console.log(array);

// 2. 提取email地址
var str = "123123@xx.com,fangfang@valuedopinions.cn 286669312@qq.com 2、emailenglish@emailenglish.englishtown.com 286669312@qq.com...";
var array = str.match(/\w+@\w+\.\w+(\.\w+)?/g);
console.log(array);

// 3. 分组提取  
// 3. 提取日期中的年部分  2015-5-10
var dateStr = '2016-1-5';
// 正则表达式中的()作为分组来使用,获取分组匹配到的结果用Regex.$1 $2 $3....来获取
var reg = /(\d{4})-\d{1,2}-\d{1,2}/;
if (reg.test(dateStr)) {
  console.log(RegExp.$1);
}

// 4. 提取邮件中的每一部分
var reg = /(\w+)@(\w+)\.(\w+)(\.\w+)?/;
var str = "123123@xx.com";
if (reg.test(str)) {
  console.log(RegExp.$1);
  console.log(RegExp.$2);
  console.log(RegExp.$3);
}

正则替换

// 1. 替换所有空白
var str = "   123AD  asadf   asadfasf  adf ";
str = str.replace(/\s/g,"xx");
console.log(str);

// 2. 替换所有,|,
var str = "abc,efg,123,abc,123,a";
str = str.replace(/,|,/g, ".");
console.log(str);

案例:验证表单

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>表单验证</title>
</head>

<body>
    <label for="txtQQ">QQ号:<input type="text" id="txtQQ"><span></span></label><br>
    <label for="txtEmail">邮箱:<input type="text" id="txtEmail"><span></span></label><br>
    <label for="txtPhone">手机:<input type="text" id="txtPhone"><span></span></label><br>
    <label for="txtBirth">生日:<input type="text" id="txtBirth"><span></span></label><br>
    <label for="txtName">姓名:<input type="text" id="txtName"><span></span></label><br>
    <script>
        // 1.验证QQ号
        addCheck('txtQQ', /^\d{5,12}$/, '请输入正确的QQ号格式');
        addCheck('txtEmail', /^\w+@\w+(\.\w+)+$/, '请输入正确的邮箱格式');
        addCheck('txtPhone', /^[1-9]\d{10}$/, '请输入正确的手机号格式');
        addCheck('txtBirth', /^\d{4}-\d{1,2}-\d{1,2}$/, '请输入正确的日期格式');
        addCheck('txtName', /^[\u4e00-\u9fa5]{0,}$/, '请输入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 = '';
                }
            }
        }

        // onchange 改变
    //     var txtQQ = document.getElementById('txtQQ');
    //     // txtQQ.onchange = function () {
    //     //     console.log("111");
    //     // }
    //     // 当光标离开文本框的时候
    //     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 = '';
    //         }
    //     }
    </script>
</body>

</html>

这篇文章有 541 个评论

  1. adultfriendrfinder

    Good post. I learn something totally new and challenging on websites I stumbleupon every day.
    It will always be interesting to read content from other authors and
    use something from other sites.

  2. online sale

    I’m amazed, I have to admit. Rarely do I come across a blog that’s equally educative and engaging, and without a doubt, you have
    hit the nail on the head. The issue is something
    that too few folks are speaking intelligently about. Now i’m very happy I came across this during my hunt
    for something relating to this.

  3. instagram takipci satin al

    Hi there, I found your blog by the use of Google while looking for a similar subject, your
    web site got here up, it appears to be like good.
    I’ve bookmarked it in my google bookmarks.

    Hi there, simply turned into aware of your weblog thru Google,
    and found that it is really informative. I’m gonna be careful for brussels.
    I will be grateful in the event you continue this
    in future. A lot of other folks can be benefited out of your writing.
    Cheers!

  4. instagram takipci satin al

    I every time spent my half an hour to read this website’s content every day along with a cup of coffee.

  5. real

    Hi to every one, as I am in fact eager of reading this
    blog’s post to be updated on a regular basis. It contains pleasant
    information.

  6. replica jordan 4

    I’ve been browsing online greater than 3 hours these days, but I never found any interesting article like yours.

    It’s beautiful price enough for me. In my view, if all web owners and bloggers made good content as you did, the
    web will likely be a lot more helpful than ever before.

发表评论