23 函数的参数及问题、作用域、预解析(变量提升)、函数返回值、获取非行间样式、函数封装
函数的参数
-
形参: 形式参数 接收实参传递过来的数据 function后面的()
-
实参: 具体的数据 传递给形参的数据 调用的()
-
arguments: 实参的集合 每个函数都有 当形参和实参的个数不确定的时候
-
number string boolean null undefined object array function
function getType(a){
console.log(a);
console.log(typeof a);
}
getType('123');
getType(true);
getType(null);
getType(undefined);
getType({name: '张三'});
getType([1,2,3,4]);
function b(){
console.log(1);
}
getType(b);
函数的问题
-
函数名重复的时候 后面的覆盖前面
function b(){
console.log(1);
}
getType(b);
// 问题: 1. 函数名重复的时候 后面的覆盖前面
function b(){
console.log(333);
}
console.log(b); -
函数的参数个数不对应的时候
形参个数多于实参个数, 多余的形参会被赋值成undefined
实参个数多于形参个数, 多余的实参就不能通过形参获取, 但是可以通过arguments获取
function fn1(a, b, c){
console.log(a, b, c);
console.log(arguments);
}
// fn1(1, 2, 3); // a = 1 b = 2 c = 3
fn1(1, 2);
fn1(1,2,3,4);
作用域
作用域: 对变量或函数起作用的区域
对某一个变量或者函数有访问权限的区域
域:区域 范围
作用:读(获取) 写(设置)
作用域的分类
-
全局作用域: 函数外的区域 script标签下的区域
-
局部作用域: 函数内的区域 function(){ 局部作用域 }
也叫做: 函数作用域
// 全局
var a = 20;
function sum(){
// 局部
console.log(1);
console.log(a);
}
变量和函数分类
根据函数和变量声明位置的不同,分为全局变量、全局函数、局部变量、局部函数
-
全局作用域中, 用var声明的变量 就是全局变量 可以在页面的任何位置被读写
用function声明的函数 就是全局函数 可以在页面的任何位置被读写
-
局部作用域中, 用var声明的变量 就是局部变量 只能在声明的函数内部进行使用 出了{}就会被销毁
用function声明的函数 就是局部函数 只能在声明的函数内部进行使用 出了{}就会被销毁
// 全局
var a = 20;
function sum(){
// 局部
console.log(1);
console.log(a);
}
console.log(a); // 20
sum(); // 20
function fn(){
var b = 30;
console.log(b);
function fn1(){
console.log(1);
}
fn1();
}
fn(); // 30
// console.log(b); // 报错
// fn1(); 报错
作用域链
作用域链: js中的一种查找方式, 决定了变量和函数向上查找的方式
// var a = 20;
// function sum(){
// console.log(a);
// }
// sum();
// var a = 30;
// function sum(){
// var a = 40;
// console.log(a);
// }
// sum(); // 40
var a = 30;
function sum(){
a = 40;
console.log(a);
}
sum(); // 40
预解析(变量提升)
-
找 找var和function 将var声明的变量 声明提到最前, 变量值是undefined, 将function声明的函数整个提到最前,存储在内存中
-
从上往下逐行解析
变量赋值在从上到下逐行解析过程中 遇到 赋值运算符 = += -= *= /= %= 会进行赋值 遇到其他运算符正常计算; 函数在遇到调用代码的时候,会形成新的局部作用域来执行代码
例子一
console.log(a);
var a = 20;
function sum(){
console.log(a);
}
sum();
/*
---------------解析过程---------------
var a;
function sum(){
console.log(a);
}
console.log(a); undefined
a = 20;
sum(); 20
*/
例子二
// 变量名 和 函数名重复的时候 后面的覆盖前面的
console.log(a);
var a = 3;
console.log(typeof a);
function a() {
alert('1');
}
// a();
var a = 4;
console.log(a);
// a();
function a() {
alert(5);
};
// a();
console.log(a);
// -------解析步骤--------
/* var a; // 13
var a; // 19
function a() { // 15
alert('1');
}
function a() { // 22
alert(5);
};
console.log(a); // 12 22行的函数
a = 3; // 13
console.log(typeof a); // 14 number typeof 3 ---> number
a(); // 18 报错 a = 3 不是函数
a = 4; // 19
console.log(a); // 20 4
a(); // 21 报错
a(); // 25 报错
console.log(a); // 26 4 */
例子三
// 用变量声明函数的时候 函数有没有名字 都不提前 用了 字面量声明函数这种方式,只会将函数名提到最前
console.log(a);
console.log(d);
var a = 3;
var d = function a() {
alert('1');
};
console.log(a);
console.log(d);
a();
// ----解析过程----
// var a; // 15
// var d; // 17
// console.log(a); // 13 undefined
// console.log(d); // 14 undefined
// a = 3; // 15
// d = function () { // 17行
// alert('1');
// };
// console.log(a); // 20 3
// console.log(d); // 21 function
// a(); // 22 报错
例子四
/*
当遇到函数调用的时候,新的局部作用域来执行代码, 由于在新的局部作用域中 相当于上下文的执行环境进行了改变 函数中的代码要按照解析顺序重新执行
*/
function fn(a) { // 形参 类似于变量 a === var a
console.log(a);
var a = 3;
console.log(a);
}
fn(2);
// ----解析步骤-----
// function fn(a) { // 形参 类似于变量 a === var a; var a;
// // 什么时候传参 调用的时候传参 形参赋值 在 var a后面赋值
// a = 2;
// console.log(a); // undefined 2
// a = 3;
// console.log(a); // 3
// }
// fn(2);
例子五
var a = 4;
function fn(b) {
console.log(a);
var a = 3;
console.log(a);
};
fn();
console.log(a);
// ------解析步骤------
// var a; // 12
// function fn(b) { // 13 b === var b
// // console.log(a);
// // var a = 3;
// // console.log(a);
// // ----解析步骤----
// var a; // 15
// console.log(a); // 14
// a = 3; // 15
// console.log(a); // 16
// };
// a = 4; // 12
// fn(); // 14---undefined 16---3 a--局部a
// console.log(a); // 全局a 4
例子六
var a = 4;
function fn(a) {
console.log(a);
a = 5;
};
fn(a);
console.log(a);
// ----解析过程----- 传参 变量名一样
// var a; // 14
// function fn(a) { // 15 a === var a a---局部a a = 4
// console.log(a); // 局部a = 4
// a = 5; // 局部a a = 5
// };
// a = 4; // 14 全局a
// fn(a); // 21 实参a---全局a---a=4 fn(4);
// console.log(a); // 22 全局a 4
例子七
function fn(a) {
var s = a;
s.name = '优就业';
};
var json = {
name: '小u'
};
fn(json);
console.log(json);
// 解析过程 对象---存储问题---内存中:声明在栈 存储在堆 16进制地址
// var json;
// function fn(a) { // var a; a = json的地址
// // var s = a;
// // s.name = '优就业';
// // -------
// var s;
// s = a;
// s.name = '优就业';
// };
// json = {
// name: '小u'
// };
// fn(json); // fn(16进制地址)
// console.log(json); // 通过16进制地址访问数据 {name: '优就业'}
函数返回值
每个函数执行结束以后都会有一个返回值
在调用的时候接收: var 变量 = 函数名();
没有设置返回值的时候,默认返回undefined
设置返回值:
return 值;
函数遇到return, 直接结束, 后续代码不在执行
使用场景:
当函数内的数据 要在函数外使用的时候 要在函数外获取的时候 将这个数据作为返回值返回出去
function a(){
console.log(1);
}
var res = a();
console.log(res);
function b(){
return 30;
}
var res1 = b();
console.log(res1);
function c(){
console.log(1);
return 20;
console.log(2);
console.log('好开心呀');
}
var res2 = c();
console.log(res2);
当返回多个数据的时候:数组、对象
数组: 返回的数据必须按照规定好的顺序返回,如果有一个错,有可能所有的都错
对象: 返回的数据通过属性名直接获取,不受其它数据影响, 代码比较冗余
建议是用对象作为返回值
function sum(){
var s = 0;
for(var i = 0; i <= 100; i++){
s += i;
}
console.log(s);
// json格式 属性名:属性值
var obj = {
m: 0,
s: s,
i: i
};
return obj;
// return [0, s, i];
// return [s, i];
// return s;
// return i;
// return s,i;
// return s;
}
var a = sum();
console.log(a);
// console.log(s); // s是局部变量 报错
// console.log('总和是:', a[0]);
console.log('总和是:', a.s);
返回值类型
返回值的数据类型:
number string boolean null undefined array object function
一般不设置null和undefined
function getReturn(){
// return 50;
// return '1234';
// return true;
// return null;
// return undefined;
// return [23, 45];
// return {
// s: 5050,
// i: 101
// };
function fn(){
console.log(1);
}
return fn;
}
var a = getReturn();
console.log(a);
console.log(typeof a);
// 如果a是true 弹出1
// if(a){
// alert(1);
// }
if(typeof a == 'function'){
// 调用函数
a();
}
// fn(); // 局部函数 在全局中不能直接用
获取非行间样式
标准(ie9以上): getComputed(元素).属性名
ie678: 元素.currentStyle.属性名
// 标准
// console.log(getComputedStyle(div));
// console.log(getComputedStyle(div).width); // 200px
// console.log(getComputedStyle); // ie678 “getComputedStyle”未定义 变量未声明
// ie678
// console.log(div.currentStyle); // 标准: undefined ie678: 对象
// console.log(div.currentStyle.width); // 200px
// 判断当前是什么浏览器
// 如果currentStyle不是undefined 不为假 就是ie678
if(div.currentStyle){
// ie678
console.log(div.currentStyle.width); // 200px
} else {
// 标准
console.log(getComputedStyle(div).width); // 200px
}
var p = document.getElementsByTagName('p')[0];
if(p.currentStyle){
// ie678
console.log(p.currentStyle.width); // 200px
} else {
// 标准
console.log(getComputedStyle(p).width); // 200px
}
函数封装
-
创建一个空函数
-
重复代码放入
-
原位置上调用 解决报错
-
抽参 分析可变的数据 抽取成参数 从上到下 逐行分析
-
传参调用 谁抽取出来 就把谁传进去
-
设置返回值
-
接收返回值 var 变量 = 函数();
var p = document.getElementsByTagName('p')[0];
// 元素.属性名 元素['属性名']
var wid = getStyle(p, 'width');
var hei = getStyle(p, 'height');
// 判断当前p的宽度如果是200 变成300
// console.log(w); // 局部变量 要想在全局中拿到 需要用return设置返回值
console.log(wid, hei);
if(wid == '200px'){
alert(1);
}
// attr--形参 类似变量
function getStyle(ele, attr) {
// ele: 元素
// attr: 属性名
var w = 0;
if (ele.currentStyle) {
// ie678
// console.log(ele.currentStyle[attr]);
w = ele.currentStyle[attr];
} else {
// 标准
// console.log(getComputedStyle(ele)[attr]); // 200px
w = getComputedStyle(ele)[attr];
}
return w;
}

浙公网安备 33010602011771号