总结一下咱们JS中的this和return的用法

1、全局中的this ,指的是window

console.log(this);//window
function abc(){
    console.log(this)//window
}
abc();

2、事件中的this

什么是事件,当前这个函数,在addEventListener中被传入第二个参数,当前这个函数有且仅有一个参数,是e,并且这个e是基于event的对象

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 返回数据

1、返回数值
function fn1( n, m ) {
            return n + m;
        }
        console.log( fn1( 2, 3 ) ); //5
2、返回一个布尔值
    function fn2( num ) {
            return num > 5;
        }
        // 返回表达式,就是返回表达式的结果,结果就一定是个布尔值
        console.log( fn2( 7 ) ) //true
        // 下面这种与上面相同,但是更加简单
        function fn2( num ) {
            if ( num >= 5 ) {
                return true;
            } else {
                return false;
            }
        }

9、return返回对象

工厂模式,函数中有一个var定义了一个对象,并且将这个对象返回出来(传递给外面),每次创建都将是一个新的对象
 
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清理掉了

 

posted @ 2022-01-10 00:37  thomas_001  阅读(426)  评论(0)    收藏  举报