JavaScript函数和对象

函数、对象

一. 目标

  • 使用arguments获取函数的所有参数 arguments是一个伪数组,可以暂且作为一个数组使用,也有参数,获取参数:实参的值赋值给形参

  • 预解析: 预解析就是程序执行代码之前会先解析,将变量名提到当前作用域的顶部,变量的值保留不变,函数整体提升到当前作用域的顶部,优先级是函数整体比变量名要优先提升到顶部,然后自上而下解析代码

  • 作用域和作用域链: 作用域分为:局部作用域----局部变量 全局作用域-----全局变量

  • 匿名函数和自调用函数

  • 对象的组成

  • 创建自定义构造函数和创建对象

  • new关键字的执行过程

  • 不同情况下this的指向

  • 遍历对象的成员和删除对象成员

  • 函数也是一种数据类型

二. 函数

2.1 函数体内的arguments

  • 思考

    写一个函数,实现计算用户输入任意个数字的总和 ?

  • arguments

    • arguments,在函数体内可以使用。arguments中存放了所有的实参。
    • arguments的使用:
    function getSum(){
     //arguments可以暂时看成是一个函数内部提供的数组,集合了所有的实参。
     //arguments.length;  参数的个数
     //arguments[下标];   //获取一个实参
     var sum = 0;
     for(var index = 0;index
    

2.2 预解析

  • 思考:

    • 思考1?:
    alert(a);  //报错
    • 思考2:
    /*
     对于js的执行顺序,默认是自上而下执行。
     对第一个alert(a)之前并没有创建变量。按道理应该报错。
    */
    alert(a);     //但是不会报错
    var a = 123;
    alert(a); 
    • 思考3:
    fn();   //报错
    //函数表达式
    var fn = function(){
     alert(1);
    };
    • 思考4:
    fn(); //不报报错
    //函数声明
    function fn() {
     alert(1); 
    }
  • 什么是预解析

    ​ 程序准备→执行。程序在执行之前,有个预备过程。 预备过程要做的事就是预解析。预备过程要做两件事,分别是:

    • 把用var关键字所声明的变量名(仅仅是变量名),提升到当前执行环境的顶部。
    • 把用函数声明所创建的函数(函数整体),提升到当前执行环境的顶部。

2.3 作用域

  • 什么是作用域?

    作用域,指的是变量或函数调用的使用范围。

  • 全局作用域

    • 什么是全局作用域?
    > 函数之外的执行环境,就是全局作用域。
    
    • 全局变量
    > 在全局作用域中用var关键字所创建的变量,就是全局变量。
    > 
    > 全局变量的作用范围是程序中的任何地方。
    > 
    >
    > var a = 123;   //a是全局变量
    > function fn() {
    >  alert(a);   //123;
    > }
    > fn();
    > alert(a);  //123;
  • 局部作用域

    • 什么是局部作用域?
    > 函数体内的环境,就是局部作用域。
    
    • 局部变量
    > 在局部作用域中用var关键字所创建的变量,就是局部变量。局部变量的作用范围是,仅仅是本函数体内使用。
    > 
    >
    > function fn(){
    >  var a = 123;
    >  alert(a);
    > }
    > alert(a); //报错
    • 函数的形参可以看成是局部变量
    > 
    > function fn(a) {
    >  alert(a);
    > }
    > alert(a); //报错
  • 看预解析

    • 思考?
    > 
    > var a = 123;
    > function fn(){
    >  console.log(a);  //a的值 undefined;
    >  var a = 456;
    > }
    > fn();
    > console.log(a);   //a的值 123
    • 预解析中的变量提升,说是提升到当前执行环境的顶部。 当前执行环境指的是当前作用域。
    • 在局部作用域中使用一个变量时,若局部变量 和 全局变量重名时,在局部作用域中会优先使用局部变量。
  • 作用域链

    • 代码
    var a = 1;
    function fn1(){
     var a = 2;
     var b = '2b';
     function fn2(){
     var a = 3;
     function fn3(){
     var a = 4;
     console.log(a);   //a的值 ?
     consoe.log(b);    //b的值 ?
     }
     
     }
    }
      • 什么是作用域链?​ 当访问一个变量时,会先从本作用域中去找这个变量中去找,若找不到则向上一级作用域中去找,依次类推,就形成了一个作用域链。
  • JS中没有块级作用域

    • 什么是块级作用域
    > ​ 在其他编程语言中,如java、c#等,在if语句、循环语句中创建的变量,仅仅只能在本if语句、本循环语句中使用。如下Java代码
    > 
    >
    > if(true){
    >  int num = 123;
    >  system.out.print(num);  //123;
    > }
    > system.out.print(num); //报错
    • JS中没有块级作用域
    > JS中没有块级作用域【ES5版本之前】
    > 
    > 
    > if(true){
    >  var num = 123;
    >  console.log(123); //123
    > }
    > console.log(123);  //123;

2.4 匿名函数和自执行函数

  • 匿名函数

    匿名函数就是没有名字的函数。在js中匿名函数需要配合运算符使用。如:

    //匿名函数 常用
    (function(){
    alert(1);
    });

    //匿名函数
    !function(){
    alert(1);
    };

    //匿名函数
    -function(){
    alert(1);
    };

  • 自执行函数(自调用函数)

    自执行函数就是匿名函数创建后马上执行。

    //匿名函数 常用
    (function(){
    alert(1);
    })();

    //匿名函数
    !function(){
    alert(1);
    }();

    //匿名函数
    -function(){
    alert(1);
    }();

  • 匿名函数和自定义函数的优点

    • 可以模拟块级作用域
    • 可以避免全局变量污染​

三. 对象

3.1 为什么要学习对象

​ 后面的很多知识点都是通过对象调用出来的,所以我们必须务必知道对象组织数据的方式。

3.2 什么是对象

  • 对象的概念

    从两个层面理解:

    • 生活层面,对象是单个事物抽象出来的实例。
    > ​ “万物皆对象”,一本书、一辆汽车、一个人都可以是对象,一个数据库、一张网页、一个与远程服务器的连接也可以是对象。当实物被抽象成对象,实物之间的关系就变成了对象之间的关系,从而就可以模拟现实情况,针对对象进行编程。
    
    • 数据层面,对象是一个容器,封装了属性和方法。
    > *   对象是一种数据,属于引用类型的数据
    >     
    >     
    > *   属性:对象的静态特征。
    >     
    >     
    > *   方法:对象的动态特征。
    >     
    

3.3 对象的创建方式

  • 类和对象

    > 抽象出的模板。
    
    • 对象
    > 具体的实例。
    
    • 类和对象的关系
    > 类是对象的模板,对象是类的实例。对象需要通过类来创建:具体语法如下
    > 
    > 
    > var 对象名 = new 类名();
    > > [图片上传失败...(image-907306-1516642285952)]
  • 方式一:通过Object类创建

    • Object 类是系统提供的一个类,可以直接使用。
    • 代码:
    var hero1 = new Object();  //空的对象,里面属性和方法
    //字面量创建
    //var hero1 = {};   //和new Object()性质一样,空的对象,里面属性和方法
    hero1.name = '孙悟空';
    hero1.age = 18;
    hero1.attack = function(){
     alert(this.name + '发动攻击...');
    }
    hero01.attack();
  • 方式二:通过自定义构造函数创建(自定义类)

    • 在es6之前,js中没有类的概念,但可以通过构造函数模拟。
    • 构造函数
    > 构造函数,可以用来创建并初始化对象。
    
    • 语法:
    //创建构造函数。和普通函数创建方式一样,当命名时首字母要大写(帕斯卡命名)
    function 函数名(参数1,参数2...){
     //this表示通过new创建的哪个当前的对象
     this.键 = 参数1;
     this.键 = 参数2;
     ...
    }
    ​
    //通过构造函数创建对像
    var 对象1 = new 函数名(实参1,实参2...);
     
    //new 关键字执行的过程
    ① 在函数体内创建一个空的对象(看不见)
    ② 让当前this指向这个空的对象
    ③ 通过this给当前空的对象添加键值对
    ④ 返回已经添加好所有键值对的对象给外面的变量。(看不见)
    • 代码:
    /*
     自定义构造函数(类) Hero
    */
    function Hero(name,age){
     this.name = name;
     this.age = age;
     this.sayHi = function(){
     console.log('我叫' + this.name + ',我今年' + this.age + '岁');
     }
     this.attack = function(){
     console.log(this.name + '发动攻击...')
     }
    }
    ​
    /*
     通过自定义构造函数创建对象
    */
    var wuKong = new Hero('孙悟空',18);
    wuKong.sayHi();
    wuKong.attack();
    ​
    var baJie = new Hero('猪八戒',20);
    baJie.sayHi();
    wuKong.attack();

3.4 对象的操作

  • 对象组织数据的方式:

    对象组织数据的方式是: 键值对。

    • 键,指的是属性名或方法名。
    • 值,指的是实际的数据。
  • 给对象增加属性和方法:

    • 对象名.键名 = 值;
    • 对象名['键名'] = 值;
    • 代码:
    var dog1 = {};
    dog1.name = '旺财'; //属性
    dog1['age'] = 1;    //属性
    dog1.call = function(){  //方法
     alert(this.name + '在汪汪叫...')
    }
    //注意,方法要用函数来表示
  • 访问对象中的属性和方法:

    • 对象.键名;
    • 对象[‘键名’];
    • 代码:
    var dog1 = {};
    dog1.name = '旺财'; //属性
    dog1['age'] = 1;    //属性
    dog1.call = function(){  //方法
     alert(this.name + '在汪汪叫...')
    }
    //注意,方法要用函数来表示
    dog1.call(); //调用
    console.log(dog1['name']);
    console.log(dog1.age);
  • 删除对象中的属性和方法:

    • delete 对象.键名;
    • delete 对象['键名'];
    • 代码:
    var dog1 = {
     name:'旺财',
     age:1,
     call:function(){
     alert(this.name + '在汪汪叫...')
     }
    };
    //删除之前访问
    console.log(do1.name); //旺财
    //删除
    delete dog1.name;
    //删除之后访问
    console.log(dog1.name); //undefiend
    //检测对中是否还要name属性
    console.log(dog1.hasOwnProperty('name'));  //false;
  • 检测一个对象中是否存在某个属性或方法:

    对象.hasOwnProperty('键名'); //返回boolean值,false表示不存在,true表示存在

  • 遍历对象中的键值对

    • 遍历方式 for-in
    for(var key in 对象){
     //key 是对象中的每一个键
     //对象[key]; 
    }
    • 代码
    var student1 = {
     name:'张三',
     age:17,
     gender:'男',
     scroe:100
    };
    for(var key in student1){
     console.log(student1[key]);
    }
  • 检测一个对象的数据类型

    • 对象是引用数据类型,检测对象时不要用typeof去检测,要用instanceof
    对象 instanceof 构造函数名;    //返回boolean值,true表示属于,false表示不属于
    • 代码
    /*
     创建构造函数 Person
    */
    function Person(name,age,gender){
     this.name = name;
     this.age = age;
     this.gender = gender;
    }
    // 创建一个Person类型的对象 p1
    var p1 = new Person('张三',17,'男');
    //检测对象p1是否属于Person
    console.log(p1 instanceof Person);  //true

3.5 this 指向问题

  • this 介绍

    this是一个关键字,这个关键字在程序执行时会指向不同的对象。也就是说这个this到底指向谁?得看程序的执行情况。

  • 构造函数和普通函数调用时,this指向不同的对象

    • this指向 window对象
    function Person(){
     this.name = '张三';
     console.log(this);   //window
    }
    // Person当做普通函数调用
    Person();
    • this指向被创建的实例对象
    function Person(){
     this.name = '张三';
     console.log(this);   //Person类型的一个实例对象
    }
    //Person当做构造函数调用
    var p1 = new Person();

你可能感兴趣的:(JavaScript函数和对象)