最常见的:Js代码1functionfoo() {2alert('hi, js')3}4foo()用匿名函数:Js代码1varfoo =function() {2alert('hi, js')3}4foo()改装一下,给调用的foo()加个括号:Js代码1varfoo =function() {2alert('hi, js')3}4(foo)()干脆,连foo的定义也省掉------把foo赋值语句的等号右边的东东、直接替换掉刚才括起来的foo:Js代码1(function() {2alert('hi, js')3})()先看常用的函数:1functionsayHello(name) {2vartext = 'Hello ' +name3varsayAlert =function() { alert(text)}4sayAlert()5}6sayHello('Bob')闭包的例子一句话描述:闭包是函数的局部变量,在函数return之后,仍然有值, 或者闭包是stack-frame,在函数return的时候,它不会被释放。(就好像'stack-frame'是内存分配、而非处于堆栈!)下面的代码返回一个function的引用:1functionsayHello2(name) {2vartext = 'Hello ' + name//local variable3varsayAlert =function() { alert(text)}4returnsayAlert5}6varsay2 = sayHello2('Jane')7say2()//hello JaneC函数指针和JavaScript的函数引用有着本质的不同。在JavaScript,函数引用变量既是一个函数指针,又是一个隐藏的闭包指针。在C和其他多数语言,当函数return之后,stack-frame就被销毁了,所有的局部变量也就不能访问了。在JavaScript中,如果你在函数里声明了函数,在你调用的函数renturn之后,局部变量仍然可以访问。请注意上面的例子,我们调用了变量text,它是函数sayHello2的局部变量。Example 3这个例子表明局部变量不是拷贝传递,而是引用传递。在外层函数退出时,它把stack-frame保存在内存。1functionsay667() {2//Local variable that ends up within closure3varnum = 6664varsayAlert =function() { alert(num)}5num++6returnsayAlert7}8varsayNumba =say667()9sayNumba()//667,而不是66610alert(sayNumba.toString())Example 4三个函数对某个闭包使用同一个引用,因为它们均在setupSomeGlobals()里声明的。1vargAlertNumber = gIncreaseNumber = gSetNumber =null2functionsetupSomeGlobals() {3//Local variable that ends up within closure4varnum = 6665//Store some references to functions as global variables6gAlertNumber =function() { alert(num)}7gIncreaseNumber =function() { num++}8gSetNumber =function(x) { num =x}9}10setupSomeGlobals()11//任意、多次 运行下面的函数12gAlertNumber()13gIncreaseNumber()14gSetNumber(5)//把num重新设为 515gSetNumber(-8888)//把num重新设为 -8888重新运行setupSomeGlobals()就会重新产生一个新的闭包。在JavaScript中,当你在函数里又声明一个函数,外部函数每调用一次,内部函数将再被重新产生一次。Example 5当心下面例子的循环:闭包中的局部变量可能和你最初想的不一样。1functionbuildList(list) {2varresult =[]3for(vari = 0i <list.lengthi++) {4varitem = 'item' +list[i]5result.push(function() {alert(item + ' ' +list[i])} )6}7returnresult8}910functiontestList() {11varfnlist = buildList([1,2,3])12//using j only to help prevent confusion - could use i13for(varj = 0j <fnlist.lengthj++) {14fnlist[j]()15}16}1718testList()//输出3次:'item3 undefined'Example 6下面的例子表明,闭包包含了 在外部函数退出之前、定义的任何局部变量。注意,变量alice实际上在匿名函数之后声明的。匿名函数先被声明:当函数被调用时,它可以访问alice,因为alice在闭包里。1functionsayAlice() {2varsayAlert =function() { alert(alice)}3//Local variable that ends up within closure4varalice = 'Hello Alice'5returnsayAlert6}7sayAlice()()//Hello Alice8alert(alice)//错误:alice不是全局变量,它在函数体内var了Example 7下面的例子表明,每次调用会产生各自的闭包。1functionnewClosure(someNum, someRef) {2//Local variables that end up within closure3varnum =someNum4varanArray = [1,2,3]5varref =someRef6returnfunction(x) {7num +=x8anArray.push(num)9alert('num: ' + num +10'\nanArray ' + anArray.toString() +11'\nref.someVar ' +ref.someVar)12}13}14closure1 = newClosure(40, {someVar : 'closure 1'})15closure1(5)1617closure2 = newClosure(1000, {someVar : 'closure 2'})18closure2(-10)小结读一些说明要比理解上面的例子难得多。我对于闭包的说明以及stack-frame等等在技术上可能不正确 --- 但是它们的确有助于理解在写JS中最常见的就是 if 判断,但是直接写 if(){}else{}太low ,下面是常见的几种js的if判断的写法:
/**
* js 判断的几种写法
*/
var a = 10,b = 20
console.log(a)
console.log(b)
/*最直接*/
if(a >b){
console.log('a大')
}else{
console.log('b大')
}
/*改变1*/
if(a >b) console.log('a大')
if(a <b) console.log('b大')
/*改变2*/
if(a >b) console.log('a大')
else console.log('b大')
/*最简单*/
console.log(a>b ? 'a大' : 'b大')
运行的结果不难想象应该为 undefined is ready for attaching undefine 。这是因为 button onclick 引用了 Warrior 的 attach 的方法。但是这里 button 中并没有 element 这个属性。所以 undefined。这也就是我们常说的 this 指向的问题。
我们通过 bind 的方法将我们方法绑定到指定的对象,这样我们的方法就有了 context 也就是上下文。这样就解决了问题,这样写法我们在 jquery 的事件绑定是最常见不过的了。
当然我们也可以也使用 es6 的箭头函数作为 ready 属性,这个箭头好处就是我无需再写 bind 来讲方法绑定到指定对象,箭头方法中 this 对象。
不通过这样做还是有性能问题的,
这种写法想必我们在写 react 时候会经常遇到这种写法。这样同样可以解决 this 的指向的问题。
每一次都会创建一个函数
我们对 createWarrior 进行改造。