javascript中函数理解

<!-- 函数的重要性 -->
    <script>    
        // <1>函数是第一类对象:javascrip中函数拥有对象的所有能力
                            //对象能做的任何一件事,函数都能做
                            //函数的特别之处在于它是可调用的,可以被调用来执行某项操作
        // 1.函数的创建方式
        //(1)通过字面量创建
        function foo(){

        }
        //(2)可赋值给变量,数组或者其他对象的属性
        var aa = function(){}
        var arr=[];
        arr.push(function(){})
        var bb = {};
        bb.data=function(){}
        // (3)作为函数的参数来传递
        function call(ninjiaFunction){

        }
        call(function(){})
        // (4)作为函数的返回值
        function returnNinjiaFunction(){
            return function(){}
        }
        // (5)具有动态创建和分配的属性
        var ninjiaFunction = function(){}
        ninjiaFunction.ninjia='lele'
    </script>
 <!-- 回调函数: 在执行过程中,我们建立的函数会被其他函数在稍后的某个合适的时间点"再回来调用"-->
    <script>
        var text = 'aaa';
        console.log('11',"代码开始")

        function uneless(callback){
            console.log('22','在uneless函数中')
            return callback()
        }
        function getText(){
            console.log('33','在getText函数中')
            return text
        }
        console.log('22',"代码准备就绪")
        console.log(uneless(getText) === text)
        console.log('end',"代码执行完毕")
    </script>

  

 <!-- 函数作为对象的乐趣 -->
    <script>
        var ninjia={}
        ninjia.name="ddd";//创建新的对象并为其分配一个新的属性
        var weldSword = function(){}
        weldSword.sordType = 'ddd'; //创建一个新的函数并为其分配一个新的属性

        // 实例1:存储函数
        var store = {
            nextId:1,
            cache:{},
            add:function(fn){
                if(!fn.id){
                    fn.id=this.nextId++;
                    this.cache[this.nextId]=fn
                    return true
                }
            }
        }
        function ninjia(){}
        console.log(store.add(ninjia))
        console.log(store.add(ninjia))
        // 实例2:自记忆函数
        function isPrime(value){
            if(!isPrime.cache){
                isPrime.cache={}
            }
            if(isPrime.cache[value] !== undefined){
                return isPrime.cache[value]
            }
            var isPrimeValue = value !== 0 && value !== 1
            for(var i=2;i<value;i++){
                if(value % i === 0){
                    isPrimeValue = false
                    break
                }
            }
            return isPrime.cache[value] = isPrimeValue
        }
        console.log(isPrime(5))
        console.log(isPrime(5))
        console.log(isPrime.cache)
    </script>

  

<!-- 函数的定义 -->
    <script>
        // 函数申明
        function MyFun(){
            return 1
        }
        // 函数表达式
        var myFun = function(){

        }
        // 箭头函数
        myArg => myArg * 2
        // 构造函数
        new Function('a','b','return a+b')
        // 生成器函数
        function* myGen(){
            yield 1
        }

        // 详解
        // (1)函数声明的方式:对于函数声明来说
            // 函数名是强制的,因为它是独立语句,要能被调用必须具有被引用的方式
            function dd(){

            }
            function aa(){
                function hiddenFun(){
                    return 'hh'
                }
                hiddenFun()
            }
            // 函数表达式
            var myFunc = function(callback){ //函数表达式作为变量赋值语句的一部分
                return callback
            }
            myFunc(function(){ //函数表达式作为函数调用的参数
                return function(){} //函数表达式作为函数的额返回值
            })
            // 立即函数
            (function nameFun(){})() //作为函数调用一部分,命令函数表达式会立即调用
        // 箭头函数
            var greet = name => "greeting" + name
    </script>

  

<!-- 函数的实参和形参 -->
    <script>
        // 形参是函数定义时列出的变量
        // 实参是函数调用时传递给函数的值
        // 函数的形参列表和实参列表长度可以不同,
        // 未赋值的形参求值得到的时undefined,
        // 传入额外的实参不会被赋值给任何一个命名形参
        
        // 案例1:剩余参数
        function multiMax(first,...remainNumbers){
            var sorted = remainNumbers.sort(function(a,b){
                return b-a
            })
            return first * sorted[0]
        }
        console.log(multiMax(3,1,2,3))
        // 案例2:默认参数
        function performAction(ninjia,action="sking"){
            return ninjia + ' ' +action
        }
        console.log(performAction('xiaoming'))
        console.log(performAction('xiaofang','sneak'))
    </script>

  

<!-- 隐式函数参数 this和arguments-->
    <script>
        // arguments参数是传递给函数的所有参数集合
        "use strict"
        function whatever(a,b,c){
            console.log(this)
            console.log(arguments)
            console.log(arguments.length)
            console.log(arguments[0])
        }
        whatever(1,2,3,4,5)

        // 非严格模式下,arguments作为函数参数的别名,改变
        function infiltrate(person){
            console.log(this)
            console.log(person)
            console.log(arguments[0])

            arguments[0] = 'aaa'
            console.log(person)
            console.log(arguments[0])

            person='bbb'
            console.log(person)
            console.log(arguments[0])
        }
        infiltrate('gardener')
    </script>

  

 <!-- 函数的调用 -->
    <button id="test">Click me</button>
    <script>
        // this:函数的上下文
        // this参数 的指向不仅是由定义函数的方式和位置决定的,同时还严重受到函数调用方式的影响
        // 1.作为函数调用==>fun()
        // 2.作为一个方法调用==>obj.fun()
        // 3.作为一个构造函数==>new Fun()
        // 4.通过函数的call和apply方法调用==>func.apply(obj)或者func.call(obj)

        // 作为函数调用
        function ninjia(){
            return this
        }
        function strFunction(){
            "use strict"
            return this
        }
        console.log(ninjia())
        console.log(strFunction())

        // 作为方法调用
        function whatMyContext(){
            return this
        }
        console.log(whatMyContext())//作为函数调用 window
        var getMythis = whatMyContext; //使用变量getMythis来调用函数,该函数仍然作为函数被调用,函数上下文也依然是window对象
        console.log(getMythis())

        var ninjia = {
            getMythis:whatMyContext
        }
        var ninjia2={
            getMythis:whatMyContext
        }
        console.log(ninjia.getMythis() === ninjia)
        console.log(ninjia2.getMythis() === ninjia2)


        // 作为构造函数调用-->new
        // 使用new调用函数会触发的动作
        // (1)创建一个空对象
        // (2)该对象作为this参数传递给构造函数,从而成为构造函数的上下文
        // (3)一般情况下,新的构造函数对象最为new运算符的返回值
        function Ninja(){
            this.shulk = function(){
                return this
            }
        }
        var ninjia1 = new Ninja()
        console.log(ninjia1)
        console.log(ninjia1.shulk())
        // 构造函数有返回值
        // 1.返回一个非对象类型
        function Ninjia2(){
            this.shulk=function(){
                return this
            }
            return 1
        }
        console.log(Ninjia2())//函数式调用
        var ninjia3 = new Ninjia2()//作为构造函数
        console.log(ninjia3)
        // 2.显式返回对象值
        var puppet={
            rules:false
        }
        function Emperor(){
            this.rules=true;
            return puppet
        }
        var emperor = new Emperor()
        console.log(emperor === puppet)


        // 使用apply和call方法调用
        // javascript为我们提供了一种调用函数的方式.从而可以显式地指定任何对象作为函数的上下文
        // 我们可以使用每个函数上都存在的这两种方法来完成:apply 和 call
        function Button(){
            this.clicked=false;
            this.click=function(){
                this.clicked=true
                console.log("按钮被点击过",Button.clicked)
                console.log("按钮被点击过",this)
                console.log("按钮被点击过",button)
            }
        }
        var button = new Button()
        var elem = document.getElementById("test")
        elem.addEventListener('click',button.click)

        // 强制回调函数的函数上下文
        function forEach(list,callback){
            for(var n=0;n<list.length;n++){
                callback.call(list[n],n)
            }
        }
        var wepons = [{type:'aaa'},{type:'ddd'},{type:'ffff'}]
        forEach(wepons,function(index){
            console.log(this)
            console.log(wepons[index].type)
        })



    </script>

  

<!-- // 解决函数上下文的问题
    // (1)使用箭头函数 绕过函数上下文问题
    //   箭头函数没有单独的this值,箭头函数的this与声明所在的上下文相同 
    // (2)使用bind方法,所有函数均可访问bind方法,可以创建并返回一个新函数,并绑定在传入的对象上
    -->
    <button id="test1">test1</button>
    <button id="test2">test2</button>
    <button id="test3">test3</button>
    <script>
        function Button(){
            this.clicked=false
            this.click=()=>{
                this.clicked=true
                console.log(button.clicked)
                console.log(this)
                console.log(button)
                console.log(this === button)
            }
        }
        var button = new Button()
        var elem = document.getElementById('test1')
        elem.addEventListener('click',button.click)
        // 箭头函数在创建的时候确定了this的指向.由于click箭头函数式作为对象字面量的属性定义的,
        // 对象字面量在全局代码中定义,因此箭头函数内部的this与全局代码的this相同
        var button={
            clicked:false,
            click:()=>{  //箭头函数
                this.clicked=true
                console.log(this)//window
                console.log(this==button)//false
            }
        }
        var elem=document.getElementById('test2')
        elem.addEventListener('click',button.click)

        // 使用bind方法
        var button3={
            clicked:false,
            click:function(){
                this.clicked=true
                console.log(this.clicked)
                console.log(this)
                console.log(button3 === this)
            }
        }
        var elem3 = document.getElementById("test3")
        elem3.addEventListener('click',button3.click.bind(button3))
    </script>

  

<!-- 闭包和作用域 -->
    <script>
        var outerValue = "juyongxia";
        function outerFuncton(){
            console.log(outerValue)
        }
        
        outerFuncton()

        var outerValue = 'aaaa';
        var later;
        function outerFunction(){
            var innerValue = 'bbb';
            function innerFunction(){
                console.log(outerValue)
                console.log(innerValue)
            }
            later = innerFunction
        }
        outerFunction()
        later()
    </script>
    <script>
        // 使用闭包---封装私有变量
        function Ninja(){
            var counts=0;
            this.getCounts = function(){
                return counts
            }
            this.setCounts = function(){
                counts++
            }
        }
        var ninjia1 = new Ninja()
        ninjia1.setCounts()
        console.log(ninjia1.counts === undefined)
        console.log(ninjia1.getCounts())

        var ninjia2 = new Ninja()
        console.log(ninjia2.getCounts())
    </script>
    <div id="box1">First Box</div>
    <script>
        function animateIt(elemantId){
            var elem = document.getElementById(elemantId)
            var tick = 0;
            var timer  =setInterval(function(){
                if(tick< 100){
                    elem.style.left = elem.style.top = tick +'px'
                    tick++
                }else{
                    clearInterval(timer)
                    console.log(tick)
                    console.log(elem)
                    console.log(timer)
                }
            },10)
        }
        animateIt('box1')
    </script>

  

  

原文地址:https://www.cnblogs.com/zhuMother/p/13230437.html