(函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块。)
是封装了一段可以重复调用执行的代码,通过找个代码块,能够实现大量代码的重复使用
使用函数的方式:
声明函数的方式:
JavaScript 对大小写敏感。关键词 function 必须是小写的,并且必须以与函数名称相同的大小写来调用函数。 |
// 函数名遵循变量起名的规则
function 函数名(){ // 代码块 }
var 函数名 = function(){ // 代码块 }
函数的调用:
在函数体后面,使用函数名加上小括号,实现函数的调用
function fn(){
// 代码块
}
fn(); // 函数调用
也就是直接调用,一般适用于没有返回值的函数,就相当于直接执行函数中的代码块
function fn(){
console.log('简单调用');
}
fn(); // 调用
js是基于事件模型,页面加载,用户点击,移动鼠标等等,都会产生事件,事件发生其实就是调用函数
// 事件中调用普通函数
btn.onclick = function(){
fn();
}
// 行内js调用
可以同构超链接调用函数
超链接
但是,为了防止超链接自带的点击功能和添加事件点击功能相互冲突,在给超链接添加点击事件的时候。需要把超链接本身自带的点击功能取消,也就是禁止a标签进行跳转
超链接
本质是把一个函数题复制给一个变量,这个变量就是函数名
var num = function(){
console.log('表达式声明函数');
}
num()
形参:一个省略了var关键字的变量,被称为一个特殊变量,变量的传值是一一对应的
参数有两种
function fn(num, sum) { // 形参 num = 3 sum = 4
console.log(num + sum);
}
fn(3, 4); // 实参
fn(30, 4); // 实参
fn(31, 4); // 实参
fn(32, 4); // 实参
fn(33, 4); // 实参
fn(34, 4); // 实参
fn(35, 4); // 实参
fn(36, 4); // 实参
实参的个数少于形参,如果形参参与运算会报错(因为没有实参传值的形参,是undefined)
function fn(num, sum, yum, tum) { // 形参 num = 3 sum = 4 tum=undefind
console.log(num + sum + yum + tum); // NaN
}
fn(3, 4, 5); // 实参
多余的实参的值会丢失
function fn(num, sum) { // 形参 num = 3 sum = 4
console.log(num + sum );
}
fn(3, 4, 5); // 实参
是实参的一组集合,是以数组的形式存在的
function fn() { // 形参 num = 3 sum = 4
// console.log(num + sum );\
console.log(arguments[0]);
}
fn('这么简单的函数', 4, 5, 4, 5); // 实参
定义:
具体比较
function test(a, b, c) {
console.log('a,b,c:', a, b, c);
for (let item of arguments) {
console.log(item);
}
}
test(1, 2);//a,b,c: 1 2 undefined item:1,2
test(1, 2, 3, 4);//a,b,c: 1 2 3 item:1,2,3,4
function cheng(a,b,c){
console.log("arguments个数:",arguments.length);
}
cheng(); // 不传参
console.log("形参的个数:",cheng.length);//分别输出:0 3
cheng(1,2);
console.log("形参的个数:",cheng.length); // 分别输出:2 3
其中函数的长度,也就是形参的个数,当有默认值的时候,只计算默认值前面的形参
function cheng(a,b=1,c){
console.log("arguments个数:",arguments.length);
}
cheng();
console.log("形参的个数:",cheng.length); // 输出 0 1
function cheng(a,b=1,c){
arguments[1] = 6
console.log("b:",b); // 2
}
cheng(1,2);
当代码大部分相同,把相同的保留一份,不同的变成参数
function fn(a) {
var num = 0;
for (var i = 0; i <= a; i++) {
num += i
}
console.log(num);
}
fn(50)
fn(80)
fn(90)
fn(100)
在函数内部,计算完成的值,需要在函数外部使用,就需要使用return返回值,把这个值返回给函数本身,可以在函数外部定义一个变量,来接收这个值
function fn(){
var a = 100;
return a
}
var a = fn() // 100这个值 返回给函数本身,并在函数外部赋值给变量 a
console.log(a);
什么时候使用返回值?
函数内部的值需不要在外部使用后展示,需不要返回值
可以返回任何类型
return {} // number string boolean null undefined object
function fn(){
console.log('今天天气好好啊');
// return // return后面没有返回的值,返回的结果是undefined
return // 有阻断代码的作用
console.log('小芳,今天约吗?'); // 因为在return后面 是不执行的
}
console.log(fn());
/*
el: 元素
attr: 属性
*/
var div = document.querryseletor('div')
function getStyle(el, attr) { // el = div attr = 'height'
if (window.getComputedStyle) { // true
// 标准浏览器
return window.getComputedStyle(el)[attr];
} else {
// 非标准浏览器
return el.currentStyle[attr];
}
}
var speed = getStyle(div, 'height');
一段代码中的变量或者是函数名,并不是一直会生效,限定这个名字的可用性代码范围,就是这个名字的作用域
var a = 10; // 全局变量
function fn() { // 全局函数
var b = 20; // 局部变量 -- 只能在局部作用域内被访问
console.log(a); // 局部作用域是可以访问全局作用域的变量和函数的
return function num() { // 局部函数
console.log(b);
}
// num()
return 100
}
console.log(fn()); // fn() = 100
fn()() //调用fn()中的sum()
不加var 直接写变量名
没有var关键字声明的变量,在任何位置都是全局的 但是不建议使用
function fn(){
a = 10; // 没有var关键字声明的变量,在任何位置都是全局的 但是不建议使用
}
fn()
console.log(a); //
作用域链是给函数向上查找变量提供的一种路线,或者理解为是一种查找机制
var a = 1;
function fn() {
var b = 2
function num() {
var c = 3
function sum() {
var d = 4
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
console.log(d); // 4
}
sum()
}
num()
}
fn()
语法:
//第一种
(function (){})()
//第二种
(function () {
// 代码块
}())
//例子
(function () {
console.log(1);
})()
注意:如果自执行函数上一行代码没有分号结尾 或报错
自执行函数上一行没分号报错的,解决方法:
var a = 10
// ~:解决上一行代码没有分号结尾的问题
~(function () {
console.log(1);
})()
其他写法:
()
小括弧可以把function
关键字作为函数声明的含义转换成函数表达式外,&&
与操作、||
或操作、,
逗号等操作符也有这个效果。true && function () { console.log("true &&") } (); // "true &&"
false || function () { console.log("true ||") } (); // "true ||"
0, function () { console.log("0,") } (); // "0,"
// 此处要注意: &&, || 的短路效应。即: false && (表达式1) 是不会触发表达式1;
// 同理,true || (表达式2) 不会触发表达式2
!
~
-
+
),函数同样也会立即执行。 !function () { console.log("!"); } (); //"!"
~function () { console.log("~"); } (); //"~"
-function () { console.log("-"); } (); //"-"
+function () { console.log("+"); } (); //"+"
new
关键字:// 注意:采用new方式,可以不要再解释花括弧 `}` 后面加小括弧 `()`
new function () { console.log("new"); } //"new"
// 如果需要传递参数
new function (a) { console.log(a); } ("newwwwwwww"); //"newwwwwwww"
=
同样也有此效用(例子中的i
变量方式)://此处 要注意区分 i 和 j 不同之处。前者是函数自执行后返回值给 i ;后者是声明一个函数,函数名为 j 。
var i = function () { console.log("output i:"); return 10; } (); // "output i:"
var j = function () { console.log("output j:"); return 99;}
console.log(i); // 10
console.log(j); // ƒ () { console.log("output j:"); return 99;}
前者是函数自执行后返回值给i
;后者是声明一个函数,函数名为j
。如果是看代码,我们需要查看代码结尾是否有没有()
才能区分。一般为了方便阅读,我们会采用下面这种方式:
var i2 = (function () { console.log("output i2:"); return 10; } ()); // "output i2:"
var i3 = (function () { console.log("output i3:"); return 10; }) (); // "output i3:"
var utils = (function () {
/*
@获取非行间样式
@obj:元素
@attr:属性
*/
function getStyle(obj, attr) {
if (window.getComputedStyle) {
return window.getComputedStyle(obj)[attr]
} else {
return obj.currentStyle[attr]
}
}
/*
计算和的函数
@a:传入的范围值
*/
function num(a) {
var num = 0;
for (var i = 0; i <= a; i++) {
num += i
}
console.log(num);
}
// ............
return {
getStyle: getStyle,
num: num,
}
})()
// console.log(utils); // utils = { getStyle: getStyle, num: num,}
utils.num(100)
解决下标获取不到的问题
window.onload = function () {
var li = document.getElementsByTagName('li')
for (var i = 0; i < li.length; i++) {
(function (i) { // 形参
li[i].onclick = function () {
console.log(i);
}
})(i) // 实参
}
}