JS函数

## JS函数
- 函数也是一个对象. 具有Object的所有功能
- 不同的是, 函数对象中可以保存一些可执行的代码.并且在需要的时候可以调用这些代码

#### 函数声明式创建
     function 函数名 (形参){
            语句
        }
     函数调用: 函数名(实参)

- 如果需要函数中的代码执行. 则要对函数进行调用
- 函数执行几次就调用几次. 

#### 函数表达式创建
    var 变量 = function (形参){
        语句
    }
    函数调用: var 变量1 = 变量()
    - 变量1当作接口接收函数
#### Function 构造函数
    var fn = new Function
#### 回调函数: 作为一个函数的参数形式存在的函数
#### 匿名回调函数: 没有变量定义的函数作为参数形式存在

    (function(){}) 
    函数调用: (); 直接使用括号来调用匿名函数

#### 自调函数: 只定义会自动调用
- () (); 
    - 第一个小括号. 定义函数
    - 第二个小括号. 调用函数(可以传递实参)
- 作用: 可以将所有全局内容改为局部内容
- ````(function({})) ();````

#### 内部函数

    function fn(){
        function n( ){ }
    }
    n();

#### 函数的形参和实参
- 定义函数时,可以在()中指定数量不等的形参
- 多个形参之间用逗号隔开
- 在函数中定义形参,就相当于在函数中声明了变量但并没有赋值
- 在调用时可以指定实参
- 实参会赋值给对应的形参

#### 形参和实参的注意事项
- JS函数在调用时,浏览器不会检查形参的类型和个数
- 实参可以是任意数据类型(可以是对象也可以是函数)
- 实参也可以是任意数量
    - 如果多于形参,则不会使用
    - 如果少于形参,则没有对应实参的形参将会是undefined

#### 函数的返回值
- 返回值简单说就是函数的执行结果
- 通过return来设置函数的返回值
- 调用函数时可以用任意变量来接收函数的返回值
- 如果没有return返回函数的值,则函数没有意义
- return 返回值可以是任意的数据类型
- return也可直接跳出函数. 后面的所有代码都不会执行


#### 方法和调用
- 当一个对象的属性是一个函数时. 称这个函数是这个对象的方法
- 函数和方法只是称呼上的不同. 本质没有区别
- 调用对象中的函数时,称之为调用对象的方法

----------

### 作用域
- 作用域简单来说就是指一个变量的作用范围
- 作用域分为两类:
    - 全局作用域
    - 函数作用域

##### 全局作用域
1. 所有直接在script标签中编写的代码都在全局作用域中
2. 全局作用域在打开网页时创建.网页关闭时销毁
3. 全局作用域中有一个全局对象: window
    - 在全局作用域中创建的变量都会作为window对象的属性保存
    - 在全局作用域中创建的函数都会作为window对象的方法保存
4. **在全局作用域中创建的变量都是全局变量.可以在任意位置访问**

##### 函数作用域
- 函数作用域可以理解为全局中的小的作用域
- 函数作用域在函数调用时创建,在调用结束时销毁
- 每调用一次函数就会创建一个新的函数作用域
- 在函数作用域中可以访问到全局变量
- **但在全局作用域中无法访问到函数作用域中的变量**
- 函数中创建的变量如果不写 var 则会变成全局变量

##### 查找变量的机制
- 在函数中使用一个变量时,它会先在自身的作用域中寻找
- 如果有就直接使用,如果没有则去上一级作用域中寻找
- 找到则使用,如果没找到,则继续寻找,直到找到全局作用域为止
- 如果全局作用域中依然没有,**则会报错**

----------

### 声明提前
##### 变量声明提前
- 使用var关键字声明的变量,会在所有的代码执行前被声明,但不会被赋值
- 值为undefined
- 如果声明一个变量不使用var关键字,则不会有声明提前的特性.它会等到代码执行时才创建

##### 函数声明提前
- 使用函数声明式创建的函数,会在所有的代码执行之前被创建
- 可以在函数声明之前就能对该函数进行调用

----------

### this
1. 以构造函数形式调用.this就代表即将new出来的对象
2. 以函数的形式调用或在全局环境下 this就是window  fn()
3. 函数作为对象的属性并被调用时. this是调用方法的对象 obj.fn()
4. 使用call和apply调用时,this是第一个参数
5. 回调函数中的this:不是我们指定的
    - dom事件回调函数中的this  -- dom元素
    - 定时器回调函数  -- window
    - arr.forEach(function(index,item){})  -- window


----------

#### 工厂函数
- 返回值是一个对象
- 解决了字面量创建多个对象有重复代码的问题

         function createPerson (name,age){
          var obj = new Object();
          obj.name=name;     
          obj.age=age
         
          obj.sayName=function( ){
               console.log("大家好,我是:"+this.name+"年龄:"+this.age+"性别:"+this.gender);
               };
        
          return obj;
           }
        
          var person=createPerson("孙悟空",18,"男");

#### 构造函数
- 构造函数专门用来创建对象的函数
- 构造函数需要通过 new 关键字来创建
- 构造函数首字母一般都是大写

###### 构造函数执行流程
1. 创建新的对象
2. 将新创建的对象设置为函数中的this
3. 逐行执行函数
4. 将新创建的对象作为返回值返回

**如果以构造函数的形式调用. this就是构造函数创建出来的对象**

- 使用同一个构造函数创建的对象称之为一类对象
- 通过构造函数创造的对象称之为该函数的实例对象

###### instanceof
- 可以检查一个对象是否是一个构造函数的实例对象
- 语法: 对象 instanceof 构造函数
- 所有的对象都是Object实例对象的后代

#### 原型 prototype
- 每创建一个函数,浏览器都会为函数添加一个原型属性
- 这个属性对应是一个对象 称之为原型对象
- 当以构造函数的形式调用函数时, 它所创建的对象中都会有一个隐式原型属性__proto__
- 可以通过隐式原型属性来访问对象
- 添加属性可以在prototype上添加使其构成原型链

#### 原型的注意事项
- 原型就相当于一个公共区域.我们可以把对象中共有的属性共有的方法统一保存到该区域里
- 这样不用添加多个重复的属性或方法,也不会污染全局作用域
- 当我们去调用一个对象的属性或方法时,它会先去对象自身中寻找
- 如果找到则直接使用,如果没找到,则去原型对象中寻找.
- 如果原型中有则返回原型中的值
- 如果原型中没有,则去原型的原型中寻找.找到了则直接使用,以此类推
- 会一直找到Object的原型中
- Object.prototype.__proto__ 为null
- 如果它里面依然没有,则**返回undefined**

###### hasOwnProperty()
- 检查一个属性是否属于对象自身

原文地址:https://www.cnblogs.com/huifang/p/7341943.html