总结一下咱们JS中的this和return的用法
1、全局中的this ,指的是window
console.log(this);//window function abc(){ console.log(this)//window } abc();
let div = document.createElement( "div" ); div.style.width = "40px"; div.style.height = "40px"; div.style.backgroundColor = "red"; document.body.appendChild( div ); div.addEventListener( "click", clickHandler ); function clickHandler( e ) { console.log( this ) //div }
3、混入this
call,apply,bind三种都可以混入对象,this将代表这个对象
function getSum( num ) { this.a += num; } let obj = { a: 0 } let obj1 = { a: 10 } let obj2 = { a: 20 } getSum.call( obj, 10 ); console.log( obj.a ) //10 getSum.apply( obj1, [ 10 ] ); console.log( obj1.a ); //20 getSum.bind( obj2 )( 10 ); console.log( obj2.a ) //30
4、对象中的this
对象中的this就是指当前的这个对象
let obj={ a:1, b:2, c:function(){ console.log(this.a)//1,this指的是这个obj } }
5、类中的this
首先是es6的
class Box{ constructor(){ this.num=3; } play(){ console.log(this.num)//3 console.log(this) console.log( this === obj )//true } } let obj=new Box(); obj.play(); //我们如果继续new一个对象出来,那么这时的this也指的是新new出来的这个对象, let obj2=new Box(); obj2.play()
接下来的是es5的类
function Box(){ this.num=3; } Box.prototype={ play:function(){ console.log(this.num);//3 } } let obj=new Box(); obj.paly();
通过上面的例子我们可以看出类中的this。就是通过new实例化的对象。
6、箭头函数的this
与箭头函数连用,代表父元素的前缀
let obj={ "a":1, "fun":()=>{ console.log(this) } } obj.fun()
7、常见的了类和事件中this混合模式中的this
在下面的案例中,我们这个类中有初始值num,我们要实现的是点一下然后数字+1,加到8的时候再点就不加了,类中的this和事件体的this是不一样的
这里我们有两种比较好的解决方法,1、使用bind混入this,这时候下面的this就变成ball了,但是有个问题就是就是替换了this以后,div就找不见了
这个时候我们e.currentTarget就是我们的div,但是我们最后还要删除侦听事件,bind方法会添加一个全局属性,然后去调用他,相对比较麻烦一点,那我们在下面用两种方法写一个这个案例
function Ball() { } Ball.prototype={ num:5, clickBind:null, createBall:function () { var div=document.createElement("div"); document.body.appendChild(div); div.style.width="50px"; div.style.height="50px"; div.style.backgroundColor="red"; this.clickBind=this.clickHandler.bind(this); div.addEventListener("click",this.clickBind); return div; }, clickHandler:function (e) { this.num++; console.log(this.num); if(this.num>=8){ e.currentTarget.removeEventListener("click",this.clickBind); } // console.log(e.currentTarget); } };
第二种方法:点击的时候还是使用的this.clickHandler,这个时候的this是这个Ball,这时候可以给div新增一个属性指向this,那么clickHandler:function(){}里面的this.self就是那个ball了,
删除事件侦听的时候也是this.removeEventListener("click",this.self.clickHandler);this.self是ball
但是将来是多个对象对应一个函数,多个函数侦听执行同一个对象,要给每一个对象添加一个属性,指向这个对象,就很不好了。
Ball.prototype={ num:5, createBall:function () { var div=document.createElement("div"); document.body.appendChild(div); div.style.width="50px"; div.style.height="50px"; div.style.backgroundColor="red"; div.self=this; div.addEventListener("click",this.clickHandler);
return div; }, clickHandler:function (e) {
this.self.num++;
console.log(this.self.num); if(this.self.num>=8){ this.removeEventListener("click",this.self.clickHandler); } } }; let ball=new Ball(); ball.createBall()
接下来就是咱们的return了
ps:return break continue的区别
break 表示跳出当前整个循环,也就是终止本层循环,和swich连用,表示跳出swich语句
continue 表示跳出本次循环,从下一个迭代寻花奴继续循环,内层循环执行完毕,外层代码继续运行,也就是跳出本次循环
return 直接返回函数,所有该函数体内的代码(包括循环体都不不会再执行)
8、return 返回数据
function fn1( n, m ) { return n + m; } console.log( fn1( 2, 3 ) ); //5
function fn2( num ) { return num > 5; } // 返回表达式,就是返回表达式的结果,结果就一定是个布尔值 console.log( fn2( 7 ) ) //true // 下面这种与上面相同,但是更加简单 function fn2( num ) { if ( num >= 5 ) { return true; } else { return false; } }
9、return返回对象
function fn3() { let div = document.createElement( "div" ); div.style.width = "30px"; div.style.height = "30px"; div.style.backgroundColor = "red"; return div; } let div1 = fn3(); let div2 = fn3(); console.log( div1 === div2 ) //false
再比如我们用es5创建一个类,工厂模式我的理解就是送原材料进去,然后我们new一个,就出来一个新对象,每个new出来的对象都不同,这就是工厂模式
function Ball( r ) { if ( r ) { this.r = r; } } Ball.prototype = { // 设置默认属性,如果new的时候不设置半径,创建出来的小球半径等于他的默认值 r: 20, ball: null, createBall: function ( parent ) { if ( !this.ball ) { this.ball = document.createElement( "div" ); this.ball.style.width = this.r * 2 + "px"; this.ball.style.height = this.r * 2 + "px"; this.ball.style.backgroundColor = "red"; parent.appendChild( this.ball ) } return this.ball } } let b1 = new Ball(); b1.createBall( document.body ); let b2 = new Ball(); b2.createBall( document.body ) console.log( b1 === b2 ) //false
let obj={ // 设置初始值 _instance:null, createDiv:function () { if(!this._instance){ this._instance=document.createElement("div"); } return this._instance; } }; let div1=obj.createDiv(); let div2=obj.createDiv(); console.log(div1===div2);//true
// 这里没有必要return; function fn4( obj ) { obj.a = 5; return obj; } // 与工厂模式相同 function fn5( obj ) { let obj1 = Object.assign( {}, obj ); obj1.a = 3; return obj1; }
function fn6( fn ) { return fn( 3, 5 ); } function fn7( a, b ) { return a + b; } function fn8( a, b ) { return a * b; } let s = fn6( fn7 ); let s1 = fn6( fn8 ); console.log( s, s1 );
var fn9 = ( function () { var num = 5; return { a: 1, c: function () { } } } );
我们经常在进行函数封装时,会独立出来一个js文件,他可以叫做method或者tools,是一个方法,那么我们一般封装函数的时候用自执行函数,然后来返回一个对象,这个对象里面有我们封装的方法
这样的话return就会返回一个私密的对象,我们调用的时候通过method打点或者tools打点调用。
10、返回多个元素
function fn11() { var width = "100px"; var height = "100px"; var color = "red"; return { width: width, height: height, backgroundColor: color }; }
11、返回函数体
这个经常用在我们的闭包中
function fun1(){ let sum=1; return function(){ sum++; return sum; } } let fun2=fun1(); console.log(fun2()); console.log(fun2()); fun2=null
定义的函数fun1,里面有一个sum,前面我们说过return是可以返回任何值得,包括函数,因此在该案例中我们直接返回一个function函数,同样嵌套执行以后,因为fun1这个函数执行后保存为了变量fun2,也就是说fun2就是fun1内部那个匿名函数,因此在执行fun2后就执行了一次fun1中的那个匿名函数,fun2是被保存到了外部变量,所以函数运行完后sum并没有被清理掉,因为外面有对于这个匿名函数的引用,因此,再次执行时,sum被继续连加。
直到最后fun2被赋值为null的时候,fun1当中的匿名函数引用才被切断,这时候也把这个sum清理掉了

浙公网安备 33010602011771号