23 函数的参数及问题、作用域、预解析(变量提升)、函数返回值、获取非行间样式、函数封装

23 函数的参数及问题、作用域、预解析(变量提升)、函数返回值、获取非行间样式、函数封装

函数

函数的参数

  1. 形参: 形式参数 接收实参传递过来的数据 function后面的()

  2. 实参: 具体的数据 传递给形参的数据 调用的()

  3. arguments: 实参的集合 每个函数都有 当形参和实参的个数不确定的时候

  4. 所有的数据类型都可以作为函数的参数 但是一般不用null和undefined 易于出错

    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);

函数的问题

  1. 函数名重复的时候 后面的覆盖前面

    function b(){
       console.log(1);
    }
    getType(b);

    // 问题: 1. 函数名重复的时候 后面的覆盖前面
    function b(){
       console.log(333);
    }
    console.log(b);
  2. 函数的参数个数不对应的时候

    形参个数多于实参个数, 多余的形参会被赋值成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);

作用域

作用域: 对变量或函数起作用的区域

对某一个变量或者函数有访问权限的区域

域:区域 范围

作用:读(获取) 写(设置)

作用域的分类

  1. 全局作用域: 函数外的区域 script标签下的区域

  2. 局部作用域: 函数内的区域 function(){ 局部作用域 }

也叫做: 函数作用域

// 全局
var a = 20;
function sum(){
   // 局部
   console.log(1);
   console.log(a);
}

变量和函数分类

根据函数和变量声明位置的不同,分为全局变量、全局函数、局部变量、局部函数

  1. 全局作用域中, 用var声明的变量 就是全局变量 可以在页面的任何位置被读写

    用function声明的函数 就是全局函数 可以在页面的任何位置被读写

  2. 局部作用域中, 用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

预解析(变量提升)

  1. 找 找var和function 将var声明的变量 声明提到最前, 变量值是undefined, 将function声明的函数整个提到最前,存储在内存中

  2. 从上往下逐行解析

变量赋值在从上到下逐行解析过程中 遇到 赋值运算符 = += -= *= /= %= 会进行赋值 遇到其他运算符正常计算; 函数在遇到调用代码的时候,会形成新的局部作用域来执行代码

例子一

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
}

函数封装

  1. 创建一个空函数

  2. 重复代码放入

  3. 原位置上调用 解决报错

  4. 抽参 分析可变的数据 抽取成参数 从上到下 逐行分析

  5. 传参调用 谁抽取出来 就把谁传进去

  6. 设置返回值

  7. 接收返回值 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;
}

 

 

posted @ 2021-01-09 17:09  一花一世界111  阅读(113)  评论(0)    收藏  举报