es5-函数高级
函数的定义和调用
- 命名函数
function fn(){};
- 函数表达式 匿名函数
var fun = function(){};
- 对象定义 new Function(‘参数1’,’参数2’,’函数体’)
var f = new Function('a','b','console.log("a+b")'); f(1,2); // 结果为 3 Function里面的参数必须是字符串格式 这种方法执行效率低,不方便书写,很少使用 所有函数都是Function的实例对象
函数内this的指向
- this的指向是在调用函数时确定的,调用方式的不同决定了this指向的不同
- 一般指向调用者
调用方式 | this指向 |
---|---|
普通函数调用 | window |
构造函数调用 | 实例对象 原型对象里的方法也指向实例对象 |
对象方法调用 | 该方法的所属对象 |
事件绑定方法 | 绑定事件对象 |
定时器函数 | window |
立即执行函数 | window |
改变函数内部的this指向
- call() 调用函数,改变函数this指向
fun.call(this指向,参数) var o = { name: 'andy' } function fn(a, b) { console.log(this); console.log(a+b); } fn.call(o, 1, 2) // 输出3 this指向o call的主要作用可以实现继承
- apply() 调用函数,改变函数this指向
fun.apply(this指向,[数组参数]) 该方法传递的值必须包含在数组里面 返回值就是函数的返回值,因为它就是调用函数 var o = { name: 'andy' } function fn(a, b) { console.log(this); console.log(a + b); } fn.apply(o, [1, 2]) // 输出3 this指向o // apply主要应用 比如可以借助apply借助数学内置对象求最大值 var arr = [1,66,99,4] var max = Math.max().apply(Math,arr); console.log(max) //输出99
- bind() 不会调用函数,但是可以改变函数内部的this指向
fun.bind(this指向,参数,参数) 返回指定的this值和初始化参数改造的原函数拷贝 // 使用 var o = { name: 'andy' } function fn(a, b) { console.log(this); console.log(a + b); } var fn1 = fn.bind(o, 1, 2); fn1(); // 输出3 this指向o // 不会调用原来的函数,可以改变原函数内部的this指向, // 返回的是原函数this改变之后的新函数
严格模式
- 消除了js中语法不合理的地方,减少了怪异的行为
- 消除了代码运行时一些不安全之处保证代码运行安全
- 提高编译器效率,增加运行速度
- 禁用了在ECMAScript的未来版本中可能会定义的一些语法,为未来新版本的js做好铺垫,比如加一些保留字,class enum export extends import super 不能做变量名
// 可以应用到整个脚本,或个别函数中 // 可以分为脚本开启严格模式,为函数开启严格模式
为脚本开启严格模式
- 方法
// 在代码最前面声明语句 <script> "use strict"; // 开启严格模式 // 下面的代码都会以严格模式执行 </script>
为某个函数开启严格模式
- 方法
<script> function fn() { "use strict"; } // 为fn函数开启严格模式 </script>
严格模式的问题
- 变量必须声明才可以打印赋值
- 不可以随意删除声明的变量
- 严格模式下定义的函数的this指向的是undefined
- 构造函数必须通过new来调用,this指向全局对象
- 定时器里的this指向的是window
- 函数不可以有重名的参数
- 函数不允许放在非函数代码块中
高阶函数
- 接收一个函数作为参数
- 返回值为函数
function fn(a, b, callback) {
console.log(a + b);
callback && callback();
}
fn(1, 2, function() {
console.log('我是最后调用的');
})
闭包
- 在函数内可以调用其他函数作用域中的变量可以成为闭包
- 闭包延长了变量的作用范围
// 函数可以访问其他函数作用域中的变量就可以称为闭包
function fn() {
var num = 10;
function fun() {
console.log(num);
}
fun();
}
fn();
// fun的作用域访问了 fn的局部变量,这就是闭包
- 通过闭包在全局作用域访问函数的局部作用域
// fn外面的作用域可以访问fn内部的局部变量 function fn() { var num = 10; return function fun() { console.log(num); } } var fun = fn(); fun();
- 案例
// 点击输出索引号 <body> <ul class="nav"> <li>1</li> <li>2</li> <li>3</li> <li>4</li> </ul> </body> <script> var lis = document.querySelectorAll('.nav li'); // 注册事件 for (var i = 0; i < lis.length; i++) { // 循环绑定点击事件 (function(i) { lis[i].addEventListener('click', function() { console.log(i); // 打印索引号 }) })(i) } </script>
递归函数
- 如果一个函数在内部可以调用自己,那么这个函数就是递归函数
// 用递归求1----- n的阶乘 function fn(n) { if (n == 1) { return 1 } return n * fn(n - 1) } console.log(fn(3))
浅拷贝
- 浅拷贝只拷贝一层
// 实现浅拷贝 可以用for循环把数据拷贝到o 当然也有语法糖
Object.assign(拷贝的对象, 被拷贝的对象);
// 就是后者把数据拷贝给前者
o = {}
obj = {
id: 1,
name: 'andy',
msg: {
age: 18
}
}
Object.assign(o, obj);
o.msg.age = 19 // 更改o对象的msg下的age属性
console.log(o);
console.log(obj); // obj这个对象也会被更改
深拷贝
- 深拷贝是把每一级的数据都会拷贝上
// 实现深拷贝 function fn(new_o, obj) { for (var i in obj) { item = obj[i] // 判断当前i是不是数组 if (obj[i] instanceof Array) { // 是的话 以当前i为key 创建一个数组 new_o[i] = []; // 进行递归 后将递归的值全部写入到当前i中 fn(new_o[i], item) // 判断当前i是否为对象 } else if (obj[i] instanceof Object) { // 是对象的话 以当前i为key 创建一个对象 new_o[i] = {}; // 进行递归,后将递归出的值全部写入当前i中 fn(new_o[i], item) } else { // 如果都不是就直接赋值 new_o[i] = item } } } fn(o, obj) console.log(o.msg == obj.msg); // 返回false
本博客所有文章是以学习为目的,如果有不对的地方可以一起交流沟通共同学习 邮箱:1248287831@qq.com!