基础大全(七)"/>
JavaScript基础大全(七)
文章目录
- 继承
- call()
- 子构造函数继承父构造函数中的属性
- 借用原型对象继承方法
- 函数的定义和调用
- 函数的定义方式
- 函数的调用
- 函数内部的this指向
- 改变函数内部 this 指向
- call方法
- apply方法
- bind方法
- call、apply、bind三者的异同
- 严格模式
- 什么是严格模式
- 开启严格模式
- 严格模式中的变化
- 高阶函数
- 闭包
- 变量的作用域复习
- 什么是闭包
- 闭包的作用
- 递归
- 什么是递归
- 3级标题
- 利用递归求1~n的阶乘
- 利用递归求斐波那契数列
- 深拷贝与浅拷贝
- 正则表达式概述
- 什么是正则表达式
- 正则表达式的特点
- 正则表达式在js中的使用
- 正则表达式的创建
- 测试正则表达式
- 正则表达式中的特殊字符
- 正则表达式的组成
- 边界符
- 字符类
- [] 方括号
- 量词符
- 预定义类
- 表单验证案例
- 正则替换replace
继承
call()
- call()可以调用函数
- call()可以修改this的指向,使用call()的时候 参数一是修改后的this指向,参数2,参数3…使用逗号隔开连接
function fn(x, y) {console.log(this);console.log(x + y);
}var o = {
name: 'andy'
};fn.call(o, 1, 2);//调用了函数此时的this指向了对象o,
子构造函数继承父构造函数中的属性
- 先定义一个父构造函数
- 再定义一个子构造函数
- 子构造函数继承父构造函数的属性(使用call方法)
// 1. 父构造函数
function Father(uname, age) {// this 指向父构造函数的对象实例this.uname = uname;this.age = age;
}// 2 .子构造函数
function Son(uname, age, score) {// this 指向子构造函数的对象实例3.使用call方式实现子继承父的属性Father.call(this, uname, age);this.score = score;
}
var son = new Son('刘德华', 18, 100);
console.log(son);
借用原型对象继承方法
// 1. 父构造函数
function Father(uname, age) {// this 指向父构造函数的对象实例this.uname = uname;this.age = age;
}
Father.prototype.money = function() {console.log(100000);
};
// 2 .子构造函数function Son(uname, age, score) {// this 指向子构造函数的对象实例Father.call(this, uname, age);this.score = score;
}
// Son.prototype = Father.prototype; 这样直接赋值会有问题,如果修改了子原型对象,父原型对象也会跟着一起变化Son.prototype = new Father();// 如果利用对象的形式修改了原型对象,别忘了利用constructor 指回原来的构造函数Son.prototype.constructor = Son;// 这个是子构造函数专门的方法Son.prototype.exam = function() {console.log('孩子要考试');
}var son = new Son('刘德华', 18, 100);console.log(son);
函数的定义和调用
函数的定义方式
- 方式1 函数声明方式 function 关键字 (命名函数)
function fn(){}
- 方式2 函数表达式(匿名函数)
var fn = function(){}
- 方式3 new Function()
var f = new Function('a', 'b', 'console.log(a + b)');
f(1, 2);
var fn = new Function('参数1','参数2'..., '函数体')
//注意
- Function 里面参数都必须是字符串格式
- 第三种方式执行效率低,也不方便书写,因此较少使用
- 所有函数都是 Function 的实例(对象) 函数也属于对象
函数的调用
/* 1. 普通函数 */
function fn() {
console.log('人生的巅峰');
}
fn();
/* 2. 对象的方法 */
var o = {sayHi: function() {
console.log('人生的巅峰');
}
}
o.sayHi();
/* 3. 构造函数*/
function Star() {};
new Star();
/* 4. 绑定事件函数*/
btn.onclick = function() {}; // 点击了按钮就可以调用这个函数
/* 5. 定时器函数*/
setInterval(function() {}, 1000); 这个函数是定时器自动1秒钟调用一次
/* 6. 立即执行函数(自调用函数)*/
(function() {
console.log('人生的巅峰');
})();
函数内部的this指向
这些 this 的指向,是当我们调用函数的时候确定的。调用方式的不同决定了this 的指向不同
一般指向我们的调用者.
改变函数内部 this 指向
call方法
- call()方法调用一个对象。简单理解为调用函数的方式,但是它可以改变函数的 this 指向
- 应用场景: 经常做继承.
var o = {
name: 'andy'
}
function fn(a, b) {console.log(this);console.log(a+b)
};
fn(1,2)// 此时的this指向的是window 运行结果为3
fn.call(o,1,2)//此时的this指向的是对象o,参数使用逗号隔开,运行结果为3
apply方法
- apply() 方法调用一个函数。简单理解为调用函数的方式,但是它可以改变函数的 this 指向。
- 应用场景: 经常跟数组有关系
var o = {
name: 'andy'
}
function fn(a, b) {console.log(this);console.log(a+b)
};
fn()// 此时的this指向的是window 运行结果为3
fn.apply(o,[1,2])//此时的this指向的是对象o,参数使用数组传递 运行结果为3
bind方法
- bind() 方法不会调用函数,但是能改变函数内部this 指向,返回的是原函数改变this之后产生的新函数
- 如果只是想改变 this 指向,并且不想调用这个函数的时候,可以使用bind
- 应用场景:不调用函数,但是还想改变this指向
var o = {
name: 'andy'
};
function fn(a, b) {
console.log(this);
console.log(a + b);
};
var f = fn.bind(o, 1, 2); //此处的f是bind返回的新函数
f();//调用新函数 this指向的是对象o 参数使用逗号隔开
call、apply、bind三者的异同
- 共同点 : 都可以改变this指向
不同点: - call 和 apply 会调用函数, 并且改变函数内部this指向.
- call 和 apply传递的参数不一样,call传递参数使用逗号隔开,apply使用数组传递
- bind 不会调用函数, 可以改变函数内部this指向.
- 应用场景
- call 经常做继承.
- apply经常跟数组有关系. 比如借助于数学对象实现数组最大值最小值
- bind 不调用函数,但是还想改变this指向. 比如改变定时器内部的this指向.
严格模式
什么是严格模式
- JavaScript 除了提供正常模式外,还提供了严格模式(strict mode)。ES5 的严格模式是采用具有限制性
JavaScript变体的一种方式,即在严格的条件下运行 JS 代码。 - 严格模式在 IE10 以上版本的浏览器中才会被支持,旧版本浏览器中会被忽略。
- 严格模式对正常的 JavaScript 语义做了一些更改:
1.消除了 Javascript 语法的一些不合理、不严谨之处,减少了一些怪异行为。
2.消除代码运行的一些不安全之处,保证代码运行的安全。
3.提高编译器效率,增加运行速度。
4.禁用了在 ECMAScript 的未来版本中可能会定义的一些语法,为未来新版本的 Javascript 做好铺垫。比如一些保留字如:class,enum,export, extends, import, super 不能做变量名
开启严格模式
- 严格模式可以应用到整个脚本或个别函数中。因此在使用时,我们可以将严格模式分为为脚本开启严格模式和为函数开启严格模式两种情况。
- 情况一 :为脚本开启严格模式
有的 script 脚本是严格模式,有的 script 脚本是正常模式,这样不利于文件合并,所以可以将整个脚本文件放在一个立即执行的匿名函数之中。这样独立创建一个作用域而不影响其他
script 脚本文件。
(function (){//在当前的这个自调用函数中有开启严格模式,当前函数之外还是普通模式"use strict";var num = 10;function fn() {}
})();
//或者
<script>"use strict"; //当前script标签开启了严格模式
</script>
<script>
//当前script标签未开启严格模式
</script>
- 情况二: 为函数开启严格模式
要给某个函数开启严格模式,需要把“use strict”; (或 ‘use strict’; ) 声明放在函数体所有语句之前。
function fn(){"use strict";return "123";
}
//当前fn函数开启了严格模式
严格模式中的变化
- 变量必须先声明
- 变量不能随便删除
- 构造函数调用必须new声明
- 函数的参数不能重名
- 定时器中的this指向仍然是window
- 严格模式下全局作用域函数中this指向undefined
- 不允许在非函数代码块内声明函数
- 事件、对象中的this还是指向调用者
- new实例对象this指向实例对象
严格模式对 Javascript 的语法和行为,都做了一些改变。
'use strict'
num = 10
console.log(num)//严格模式后使用未声明的变量
--------------------------------------------------------------------------------
var num2 = 1;
delete num2;//严格模式不允许删除变量
--------------------------------------------------------------------------------
function fn() {
console.log(this); // 严格模式下全局作用域中函数中的 this 是 undefined
}
fn();
---------------------------------------------------------------------------------
function Star() {
this.sex = '男';
}
// Star();严格模式下,如果 构造函数不加new调用, this 指向的是undefined 如果给他赋值则 会报错.
var ldh = new Star();
console.log(ldh.sex);
----------------------------------------------------------------------------------
setTimeout(function() {console.log(this); //严格模式下,定时器 this 还是指向 window
}, 2000);
高阶函数
- 高阶函数是对其他函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出。
- 函数也是一种数据类型,同样可以作为参数,传递给另外一个参数使用。最典型的就是作为回调函数。
- 同理函数也可以作为返回值传递回来
闭包
变量的作用域复习
变量根据作用域的不同分为两种:全局变量和局部变量。
函数内部可以使用全局变量。
函数外部不可以使用局部变量。
当函数执行完毕,本作用域内的局部变量会销毁。
什么是闭包
闭包(closure)指有权访问另一个函数作用域中变量的函数。简单理解就是 ,一个作用域可以访问另外一个函数内部的局部变量。
闭包的作用
作用:延伸变量的作用范围。
function fn() {var num = 10;function fun() {console.log(num);
}return fun;
}
var f = fn();
f();
递归
什么是递归
- 递归:如果一个函数在内部可以调用其本身,那么这个函数就是递归函数。简单理解:函数内部自己调用自己, 这个函数就是递归函数
- 注意:递归函数的作用和循环效果一样,由于递归很容易发生“栈溢出”错误(stack overflow),所以必须要加退出条件return。
3级标题
利用递归求1~n的阶乘
//利用递归函数求1~n的阶乘 1 * 2 * 3 * 4 * ..n
function fn(n) {if (n == 1) { //结束条件return 1;}return n * fn(n - 1);
}
console.log(fn(3));
利用递归求斐波那契数列
// 利用递归函数求斐波那契数列(兔子序列) 1、1、2、3、5、8、13、21...
// 用户输入一个数字 n 就可以求出 这个数字对应的兔子序列值
// 我们只需要知道用户输入的n 的前面两项(n-1 n-2)就可以计算出n 对应的序列值
function fb(n) {if (n === 1 || n === 2) {return 1;
}return fb(n - 1) + fb(n - 2);
}
console.log(fb(3));
深拷贝与浅拷贝
// 浅拷贝只是拷贝一层, 更深层次对象级别的只拷贝引用.// 深拷贝拷贝多层, 每一级别的数据都会拷贝.var obj = {id: 1,name: 'andy',msg: {age: 18}};var o = {};// for (var k in obj) {// // k 是属性名 obj[k] 属性值// o[k] = obj[k];// }// console.log(o);// o.msg.age = 20;// console.log(obj);console.log('--------------');//另一种方式的浅拷贝Object.assign(o, obj);console.log(o);o.msg.age = 20;console.log(obj);
// 深拷贝拷贝多层, 每一级别的数据都会拷贝.var obj = {id: 1,name: 'andy',msg: {age: 18},color: ['pink', 'red']};var o = {};// 封装函数 function deepCopy(newobj, oldobj) {for (var k in oldobj) {// 判断我们的属性值属于那种数据类型// 1. 获取属性值 oldobj[k]var item = oldobj[k];// 2. 判断这个值是否是数组if (item instanceof Array) {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);var arr = [];console.log(arr instanceof Object);o.msg.age = 20;console.log(obj);
正则表达式概述
什么是正则表达式
- 正则表达式( Regular Expression )是用于匹配字符串中字符组合的模式。在JavaScript中,正则表达式也是对象。
- 正则表通常被用来检索、替换那些符合某个模式(规则)的文本,例如验证表单:用户名表单只能输入英文字母、数字或者下划线,
昵称输入框中可以输入中文(匹配)。此外,正则表达式还常用于过滤掉页面内容中的一些敏感词(替换),或从字符串中获取我们想要的特定部分(提取)等 。
正则表达式的特点
- 灵活性、逻辑性和功能性非常的强。
- 可以迅速地用极简单的方式达到字符串的复杂控制。
- 对于刚接触的人来说,比较晦涩难懂。比如:^\w+([-+.]\w+)@\w+([-.]\w+).\w+([-.]\w+)*$
- 实际开发,一般都是直接复制写好的正则表达式. 但是要求会使用正则表达式并且根据实际情况修改正则表达式. 比如用户名:
/1{3,16}$/
正则表达式在js中的使用
正则表达式的创建
- 在 JavaScript 中,可以通过两种方式创建一个正则表达式。
- 方式一:通过调用RegExp对象的构造函数创建
var regexp = new RegExp(/123/);
console.log(regexp);
- 方式二:利用字面量创建 正则表达式
var rg = /123/;
测试正则表达式
- test() 正则对象方法,用于检测字符串是否符合该规则,该对象会返回 true 或 false,其参数是测试字符串。
var rg = /123/;
console.log(rg.test(123));//匹配字符中是否出现123 出现结果为true
console.log(rg.test('abc'));//匹配字符中是否出现123 未出现结果为false
正则表达式中的特殊字符
正则表达式的组成
一个正则表达式可以由简单的字符构成,比如 /abc/,也可以是简单和特殊字符的组合,比如 /ab*c/ 。其中特殊字符也被称为元字符,在正则表达式中是具有特殊意义的专用符号,如 ^ 、$ 、+ 等。
特殊字符非常多,可以参考:
MDN
jQuery 手册:正则表达式部分
正则测试工具
边界符
正则表达式中的边界符(位置符)用来提示字符所处的位置,主要有两个字符
如果 ^和 $ 在一起,表示必须是精确匹配。
var rg = /abc/; // 正则表达式里面不需要加引号 不管是数字型还是字符串型
// /abc/ 只要包含有abc这个字符串返回的都是true
console.log(rg.test('abc'));
console.log(rg.test('abcd'));
console.log(rg.test('aabcd'));
console.log('---------------------------');
var reg = /^abc/;
console.log(reg.test('abc')); // true
console.log(reg.test('abcd')); // true
console.log(reg.test('aabcd')); // false
console.log('---------------------------');
var reg1 = /^abc$/; // 精确匹配 要求必须是 abc字符串才符合规范
console.log(reg1.test('abc')); // true
console.log(reg1.test('abcd')); // false
console.log(reg1.test('aabcd')); // false
console.log(reg1.test('abcabc')); // false
字符类
字符类表示有一系列字符可供选择,只要匹配其中一个就可以了。所有可供选择的字符都放在方括号内。
[] 方括号
表示有一系列字符可供选择,只要匹配其中一个就可以了
var rg = /[abc]/; // 只要包含有a 或者 包含有b 或者包含有c 都返回为true
console.log(rg.test('andy'));//true
console.log(rg.test('baby'));//true
console.log(rg.test('color'));//true
console.log(rg.test('red'));//false
var rg1 = /^[abc]$/; // 三选一 只有是a 或者是 b 或者是c 这三个字母才返回 true
console.log(rg1.test('aa'));//false
console.log(rg1.test('a'));//true
console.log(rg1.test('b'));//true
console.log(rg1.test('c'));//true
console.log(rg1.test('abc'));//true
----------------------------------------------------------------------------------
var reg = /^[a-z]$/ //26个英文字母任何一个字母返回 true - 表示的是a 到z 的范围
console.log(reg.test('a'));//true
console.log(reg.test('z'));//true
console.log(reg.test('A'));//false
-----------------------------------------------------------------------------------
//字符组合
var reg1 = /^[a-zA-Z0-9]$/; // 26个英文字母(大写和小写都可以)任何一个字母返回 true
------------------------------------------------------------------------------------
//取反 方括号内部加上 ^ 表示取反,只要包含方括号内的字符,都返回 false 。
var reg2 = /^[^a-zA-Z0-9]$/;
console.log(reg2.test('a'));//false
console.log(reg2.test('B'));//false
console.log(reg2.test(8));//false
console.log(reg2.test('!'));//true
量词符
量词符用来设定某个模式出现的次数。
预定义类
预定义类指的是某些常见模式的简写方式.
表单验证案例
//手机号验证:/^1[3|4|5|7|8][0-9]{9}$/;
//验证通过与不通过更换元素的类名与元素中的内容
if (reg.test(this.value)) {// console.log('正确的');this.nextElementSibling.className = 'success';this.nextElementSibling.innerHTML = '<i class="success_icon"></i> 恭喜您输入正确';} else {// console.log('不正确');this.nextElementSibling.className = 'error';this.nextElementSibling.innerHTML = '<i class="error_icon"></i>格式不正确,请从新输入 ';
}
//QQ号验证: /^[1-9]\d{4,}$/;
//昵称验证:/^[\u4e00-\u9fa5]{2,8}$/
//验证通过与不通过更换元素的类名与元素中的内容 ,将上一步的匹配代码进行封装,多次调用即可
function regexp(ele, reg) {ele.onblur = function() {if (reg.test(this.value)) {// console.log('正确的');this.nextElementSibling.className = 'success';this.nextElementSibling.innerHTML = '<i class="success_icon"></i> 恭喜您输入正确';} else {// console.log('不正确');this.nextElementSibling.className = 'error';this.nextElementSibling.innerHTML = '<i class="error_icon"></i> 格式不正确,请从新输入 ';}}
};
//密码验证:/^[a-zA-Z0-9_-]{6,16}$/
//再次输入密码只需匹配与上次输入的密码值 是否一致
正则替换replace
replace() 方法可以实现替换字符串操作,用来替换的参数可以是一个字符串或是一个正则表达式
var str = 'andy和red';
var newStr = str.replace('andy', 'baby');
console.log(newStr)//baby和red
//等同于 此处的andy可以写在正则表达式内
var newStr2 = str.replace(/andy/, 'baby');
console.log(newStr2)//baby和red
//全部替换
var str = 'abcabc'
var nStr = str.replace(/a/,'哈哈')
console.log(nStr) //哈哈bcabc
//全部替换g
var nStr = str.replace(/a/a,'哈哈')
console.log(nStr) //哈哈bc哈哈bc
//忽略大小写i
var str = 'aAbcAba';
var newStr = str.replace(/a/gi,'哈哈')//"哈哈哈哈bc哈哈b哈哈"
a-z0-9_- ↩︎
更多推荐
JavaScript基础大全(七)
发布评论