函数的定义和调用
函数定义
1.函数声明方式,使用function关键字,声明命名函数
function fn(){};
2.函数表达式定义匿名函数
var func=function(){};
3.new Function(‘参数1’,‘参数2’,‘函数体’),参数和函数体要以字符串方式书写,执行效率低,书写麻烦,使用较少,所有函数都是Function的实例对象,函数属于对象
var func=new Function('a','b','console.log(a+b)');
函数调用
1.普通函数
function fn(){
console.log('人生巅峰');
}
//调用
f();//fn.call()
2.对方的方法
var 0bj={
sayHi:function(){
console.log('人生巅峰');
}
}
//调用
obj.sayHi();
3.构造函数
function Star(){};
//调用
new Star();
4.绑定事件函数
btn.onclick=function(){};
//调用
//点击按钮就会调用
5.定时器函数
setInterval(function(){},1000);
//定时器自己每隔一定时间自动调用
6.立即执行函数
(function(){
console.log('人生巅峰');
})();
//立即执行函数自动调用
this
函数内this的指向
函数不同调用方式决定了this的指向不同
1.普通函数的this指向window
2.对象的方法中this指向方法的调用者
3.构造函数的this指向实例对象,原型对象中的this也指向实例对象
4.绑定事件函数的this指向函数的调用者
5.定时器函数的this指向的是window
6.立即执行函数的this指向的是window
改变函数内部this指向
js专门提供了一些函数来处理函数内部this指向问题
1.call()
call()方法简单理解为调用函数的方式,但可以改变this的指向,主要用于实现继承
语法:func.call(thisArg,arg1,arg2,…)
thisArg:在函数运行时指定的this值
arg1,arg2:传递的其他参数
var obj={
name:'Tom'
}
function fn(a,b){
console.log(this);
console.log(a+b);
};
fn.call(obj,1,2);
2.apply()
apply()方法也是调用函数的方式,也能改变this的指向,与call不同的是参数不同,主要用于处理数组相关
语法:func.apply(thisArg,[argsArray])
thisArg:在函数运行时指定的this值
argsArray:传递的值,必须包含在数组中
返回值就是函数的返回值
var obj={
name:'Tom'
}
function fn(arr){
console.log(this);
console.log(arr);
};
fn.apply(obj,['blue']);
//apply()应用,EG:求数组的最大值
var arr=[1,2,33,99.100];
var max=Math.max.apply(Math,arr);
console.log(max);
3.bind()
bind()方法不会调用函数,但可以改变this的指向,主用于不需要立即调用函数,但又要改变this指向的场景
语法::func.call(thisArg,arg1,arg2,…)
thisArg:在函数运行时指定的this值
arg1,arg2:传递的其他参数
返回的是原函数改变this之后产生的新函数,即返回值是函数
var obj={
name:'Tom'
}
function fn(a,b){
console.log(this);
console.log(a+b);
};
var f=fn.bind(obj,1,2);
f();
//应用举例:点击按钮后禁用,5秒钟后开启
var btn=document.querySelector('button');
btn.onclick=function(){
this.disabled=true;//this指向的是按钮
setTimeout(function(){
this.disabled=false;//定时器this指向的是window,但此时this指向btn
}.bind(this),5000);//this指向的btn对象
}
严格模式
概述
javascript除了提供正常模式外还提供了严格模式(strict mode)
ES5的严格模式是采用具有限制性avascript变体的一种方式,即在严格的条件下运行代码
严格模式在IE10以上版本才支持,旧浏览器会忽略
严格模式对正常js的语义做的改变:
1.消除js语法的一些不合理、不严谨地方,减少了一些怪异行为
2.消除代码运行的一些不安全之处
3.提高了编译效率,增加运行速度
4.禁用了在ECMAScript的未来版本中可能会定义的一些语法,为新版本做铺垫。比如一些保留字不能做变量名
开启严格模式
严格模式可以应用到整个脚本或个别函数,因此分为为脚本开启严格模式和为函数开启严格模式
1.脚本开启严格模式
<script>
'use strict';//开启脚本严格模式,下面的js代码按严格,模式执行
</script>
<!--或者-->
<script>
(function(){
'use strict';
})();
</script>
2.为函数开启严格模式
给某个函数开启严格模式,把’use strict’;声明放在函数体所有语句之前
function fn(){
'use strict';//下面代码按照严格模式运行
}
function fun(){
//里面的代码按照普通模运行
}
严格模式中的变化
1.变量规定
正常模式下,变量没声明,默认全局变量。严格模式下,必须先声明后使用
禁止删除已经声明的变量,如,delete x是错误语法
2.严格模式下this指向问题
正常模式下全局作用域函数的this指向Window对象。严格模式下,全局作用域函数的this指向undefined
正常模式下构造函数不加new可以当普通函数,this指向全局对象。严格模式下,this指向会报错,加new后可以
定时器中的this没有变化
事件、对象还是指向调用者
3.函数变化
严格模式下,函数中不能有重名参数
函数声明必须放在顶层,ES6中引入了块级作用域。不允许在非函数的代码块内声明函数
更多严格模式要求可以参考:MDN:https://developer.mozilla.org
高阶函数
高阶函数就是对其他函数进行操作的函数
高阶函数接收函数作为参数或者把函数作为返回值输出
函数是数据类型,可以作为参数传递给另一参数使用,最典型的例子是回调函数
// 高阶函数,把函数作为参数,典型回调函数
function fn(a, b, callback) {
console.log(a + b);
callback && callback();
}
fn(1, 3, function() {
console.log('函数作为参数');
})
闭包
变量作用域
变量根据作用域分为全局变量和局部变量
函数内部可以使用全局变量
函数外部不可以使用局部变量
函数执行完毕,函数作用域内的局部变量会销毁
闭包
闭包是指有权访问另一函数作用域中变量的函数
简单来说就是一个作用域可以访问另一个函数内部的局部变量
//fun内部作用域访问fn内部的局部变量
function fn() {
//fn是闭包函数
var num = 1;
function fun() {
// 函数fun访问了函数fn的局部变量
console.log(num);
}
fun();
}
fn();
//fu外部作用域访问fn内部的局部变量
function fn() {
//fn是闭包函数
var num = 1;
/*function fun() {
// 函数fun访问了函数fn的局部变量
console.log(num);
}
return fun;*/
//返回匿名函数
return function(){
console.log(num);
}
}
/* var f=fn();//类似于var f=function fun(){ console.log(num);}*/
var f=fn();//类似于var f=function (){ console.log(num);}
f();
闭包的作用:延升变量的作用范围
递归
一个函数内部可以调用自身,这个函数就是递归函数
递归函数的作用和循环效果一样
递归容易发生栈溢出问题,要加退出条件
var i = 1;
function fn() {
console.log('递归');
if (i == 3) {
return;
}
i++;
fn();
}
fn();
浅拷贝和深拷贝
浅拷贝只拷贝一层,更深层对象级别只拷贝引用
深拷贝拷贝多层,每一级别的数据都会拷贝
ES6增加了浅拷贝方法:Object.assign(target,…sources)
//浅拷贝
var obj = {
id: 1,
name: 'Tom',
msg: {
age: 19
}
}
var o = {};
Object.assign(o, obj);
console.log(o);
//深拷贝
var obj = {
id: 1,
name: 'Tom',
msg: {
age: 19
},
love: ['sing', 'cook']
}
var o = {};
// 深拷贝,递归实现
function deepCopy(newObj, oldObj) {
for (var k in oldObj) {
// 判断属性值类型
// 获取属性值
var item = oldObj[k];
// 判断值是否为数组
if (item instanceof Array) {
newObj[k] = [];
deepCopy(newObj[k], item);
} else if (item instanceof Object) {
// 判断值是否为对象
newObj[k] = {};
deepCopy(newObj[k], item);
} else {
// 属性值是否为简单数据类型
newObj[k] = item;
}
}
}
deepCopy(o, obj);
console.log(o);
来源:CSDN
作者:与风的约定
链接:https://blog.csdn.net/weixin_42230956/article/details/103645890