<!-- 函数的重要性 --> <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>