js进阶知识—函数
2020-8-10~8-16 函数部分遗漏的知识将在今后学习之中慢慢总结。
函数:
1-1声明式(Function Declaration):
function fn() {
console.log('我是函数声明式');
}
// fn();两种调用方法
fn.call();
1-2表达式(Function Expression):
var fn = function(aru) {
console.log(aru);
};
//aru是形参
fn('我是函数表达式');
fn是变量名,不是函数名,里面存的是一个函数。所以也称为匿名函数。函数的表达式需要在语句的结尾加上分号,表示语句结束。
1-3 new Function()定义:
var fn = new Function(‘参数1’, ‘参数2’, …, ‘函数体’) 所有函数都是Function的实例(对象)。
var sum = new Function('a', 'b', 'console.log(a + b)');
sum(1, 2);
//所有函数都是Function的实例(对象)
//函数也属于对象
console.log(sum instanceof object);
//等同于:
function sum(a, b) {
console.log(a + b);
}
sum(1, 2);
可以传递任意数量的参数给Function
构造函数,只有最后一个参数会被当做函数体,如果只有一个参数,该参数就是函数体。Function里面的参数必须是字符串的格式。这种声明函数的方式非常不直观,较少使用。
2-1立即执行函数IIFE:
(function(a, b){ //匿名函数自调用
console.log(a + b);
})(1, 2);//函数定义完,立即被调用,立即执行函数往往只会执行一次
2-2回调函数:
定义后没有调用,但函数自己执行了。
①dom事件回调函数:
<button>点击</button>
var btn = document.querySelector('button');
btn.onclick = function() {
alert(this.innerHTML);
}
②定时器回调函数:
setTimeout(function(){
alert('2秒钟到了');
}, 2000)
2-3箭头函数:
箭头函数里面没有this, arguments不能使用
var sum = function(x, y) {
return x + y;
}; //匿名函数
var sum2 = (x, y) => {
return x + y;
}; //箭头函数,由于函数体只有一行代码,可以简写如下
var sum2 = (x, y) => x + y; //如果只有一个参数,小括号也可以省略 var sum2 = x => {}
<button>点击按钮变成红色</button>
const btn = document.querySelector('button');
btn.addeventListener('click', function() {
this.style.backgroundColor = 'red';
}); //此时点击按钮后,样式会变成红色,但改为如下所示的箭头函数后会显示backgroundColor未定义
<button>点击按钮变成红色</button>
const btn = document.querySelector('button');
btn.addeventListener('click', () => {
console.log(this === window); //true
//this.style.backgroundColor = 'red'; 将function()改为箭头函数后,为btn设置样式会显 //示未定义的报错,原因就是箭头函数里面没有this
}); //
3-1变量:
对于顶层函数来说,函数外部声明的变量就是全局变量(global variable),它可以在函数内部读取。全局变量在网页关闭后删除。在函数内部定义的变量(使用var),称为局部变量(local variable),外部无法读取。当函数执行完毕,本作用域内的局部变量会销毁。
3-2const
声明常量,常量就是值(内存地址)不能变化的量。
①不允许重复使用 ②不属于顶层对象window ③不存在变量提升 ④暂时性死区 ⑤块级作用域
const arr = [100, 200]; //复杂数据类型,数据内容可以更改,但数据值本身不可更改
arr[0] = 'a';
arr[1] = 'b';
console.log(arr); //['a', 'b'] 并没有更改arr常量在内存中的存储地址
arr = ['a', 'b']; //,而此种赋值操作则更改了arr在内存中的存储地址
const PI = 3.14;
PI = 100; //报错,因为常量声明后,值(简单数据类型)不可更改
3-3作用域(scope):
指的是变量存在的范围。在 ES5 的规范中,JavaScript 只有两种作用域:一种是全局作用域,变量在整个程序中一直存在,所有地方都可以读取;另一种是函数作用域,变量只在函数内部存在。ES6 又新增了块级作用域。
③块级作用域:一对{}就产生了块级作用域,在块级作用域中声明的变量只能在{}里访问,如es6中的let声明的变量和const声明的常量。
if(true) {
const str = 'es6';
let a = 10; //此时const和let声明的变量只在{}里面有用
}
console.log(str);
console.log(a); //会报错,如果将const 和 let改为var,则不会报错。
3-4暂时性死区:
比如在es6中,如下面代码所示的{}作用域中在num被声明之前就使用了num,会报错。
var num = 10;
if(true) {
console.log(num);
const num = 20; //或者let num = 20;
} //会报错,因为由const和let在{}里面声明的num和整个块级作用域绑在一起了,在声明之前就使用会报错, //而且不能访问{}外面的同名变量num
3-5闭包(closure)(GC):
指有权访问另一个函数作用域中变量的函数。(简单理解就是,一个作用域可以访问另外一个函数内部的局部变量)//闭包的主要作用:延伸了变量的作用范围。
function fn() {
var num = 10;
function fun() {
console.log(num);
//此时fun访问了fn作用域中的局部变量num
}
fun();
}
fn();
可以使以上代码中的内部函数fun在执行前,从外部函数返回。加一个return简化成以下代码
//fn外面的作用域也可以访问fn内部的局部变量。
function fn() {
var num = 10;
return function() {
console.log(num);
}
}
var f = fn();//此时在fn函数的外面也可以访问fn作用域里面的局部变量,局部变量也没有被销毁,因为在
f(); //fn函数的外面始终有一个f在等待着调用fn。
//类似于var f = function(){console.log(num);}
3-6 this:
①普通函数的this指向window
function fn() {
console.log('普通函数的this' + this);
}
fn();
//但是在严格模式下全局作用域中函数中的this是undefined
②对象的方法:this指向的是该方法所属对象o
var o = {
sayHi: function() {
console,log('对象的方法this:' + this);
}
}
o.sayHi();
③构造函数this指向实例对象tom,原型对象里面的this指向的也是实例对象tom
function Person() {};
Person.prototype.sing = function{};
var tom = new Person();
④绑定事件函数的this指向的是绑定事件对象btn
<button>点击</button>
var btn = document.querySelector('button');
btn.onclick = function() {
console.log('绑定事件函数的this:' + this);
};
⑤定时器函数的this指向的是window
//应该在setTimeout前面加上window
setTimeout(function(){
console.log('定时器的this:' + this);
},1000);
⑥立即执行函数的this指向window
(function(){
console.log('立即执行函数的this' + this);
})();
3-7改变函数内部this指向:
常用的有call(),apply(),bind()三种方法。
①call()方法调用一个对象。简单理解为调用函数的方式,同时它也可以改变函数的this指向。fun.call(thisArg, arg1, arg2…)
var o = {
name: 'tom'
};
function fn(a, b) {
console,log(this);
console.log(a + b);
};
//call()里面不传参数o时this指向的是window,传了之后指向对象o,同时给定参数1,2进行计算
fn.call(o, 1, 2)//tom 3
call()的主要作用可以实现继承
function Father(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
function Son(name, age, sex) {
//调用Father里面的属性,首先调用函数,然后修改this使其指向Son,同时传递参数
Father.call(this, name, age, sex);
}
var son = new Son('tom', 18, '男');
console.log(son);
②apply()方法调用一个函数,简单理解为调用函数的方式,它可以改变函数的this指向。
fun.apply(thisArg, [argsArray]) thisArg:在fun函数运行时指定的this值, argsArray:传递的值,必须包含在数组里面。
var o = {
name: 'tom'
};
function fn(arr) {
console.log(this);
console.log(arr);
};
fn.apply(o, ['参数必须是数组形式(伪数组)']);
**apply()的主要应用是:**与数组有关系,如可以利用apply借助于数学内置对象求最大值,最小值。
var arr = [1, 9, 3, 6, 5];
var max = Math.max.apply(Math, arr);
//指向函数max的调用者Math
var min = Math.min.apply(Math, arr);
console.log(max, min);//9
③bind()方法不会调用函数,但是能改变函数内部this指向。
fun.bind(thisArg, arg1, arg2, …) thisArg:在fun函数运行时指定的this值,arg1,arg2:传递的其他参数,返回由指定的this值和初始化参数改造的原函数拷贝。
var o = {
name: 'tom'
};
function fn(a, b) {
console.log(this);
console.log(a + b);
};
//不会调用原来的函数
var f = fn.bind(o, 1, 2);
//返回的是改变this之后产生的新函数
f();//返回o对象 和 3
有的函数我们不需要立即调用,但是又想改变这个函数内部的this指向,此时用bind的方法最合适。
创建一个按钮,当我们点击了之后,就禁用这个按钮,3秒钟之后开启
<button>点击</button>
var btn = document.querySelector('button');
btn.onclick = function() {
this.disabled = true;//这个this指向的是btn
setTimeout(function(){
//不能直接写this.disabled = false;因为此时的this指向的是window。解决方法:
//可以在setTimeout上面声明一个var that = this;然后在setTimeout里面将this改为
//that.disabled,但是这种办法很麻烦要新开辟一块内存空间存放that。
//最佳方法是在定时器函数的外面绑定bind()方法
this.disabled = false;//加了bind方法之后this指向btn(点击对象)
}.bind(this), 3000);
}
上一篇: 《JavaScript高级程序设计》读书笔记(六)
下一篇: python实现抛掷硬币
推荐阅读
-
JS函数和JS事件知识总结
-
js进阶知识—函数
-
Android进阶知识(十八):View动画、帧动画与View动画的特殊应用
-
手动实现JavaScript中的bind函数 博客分类: js 开发 手动实现JavaScript中的bind函数
-
海创软件组--20200906--Vue项目设置浏览器小图标--JS中使用Element的消息确认框并可触发回调函数!!
-
js构造函数与原型对象的区别与联系
-
JS函数式编程究竟是什么?
-
进入页面就加载多个js函数 博客分类: web前端 JavaScriptjsjqueryreload
-
原生js实现jquery函数animate()动画效果
-
js中的回调函数(callback)