JS面向对象编程 一

1:构造函数和new命令

对象相当于一个实物的抽象,其中封装了属性和方法(可以用一个变量,函数等作为对象),而在面向对象编程语言之中存在一个“类”的概念,这个类就相当于是对象的模板,对象就相当于是类的实例。但是在JS之中,没有这个类,对象是基于构造函数以及原型链,也就是说,构造函数是对象的模板,对象是构造函数的实例
构造函数当做模板,使用new命令执行,并且返回实例对象
构造函数特点:

1:使用this关键字
2:在执行时使用new命令

new命令
基本用法:1:可以执行构造函数,返回一个实例对象
2:使用new命令时,根据需要,构造函数可以添加参数
3:执行构造函数的时候,构造函数后面可以加括号,也可以不加括号
如果某个构造函数没有使用new命令,就相当于是一个普通函数,此时,函数里面的this指向的就是全局变量,而不会生成一个实例对象,如果想要解决这种问题
第一种方法:使用严格模式,在函数的第一句加上use strict,如果没有使用new命令,this就会指向全局变量,而在严格模式下面,函数内部的this不能指向全局变量,此时,就会报错
第二种方法:使用函数判断是否使用new命令

<script>
    function a(foo,bar){
        if(!(this instanceof a)){
            return new a(foo,bar);
        }
        this._foo=foo;
        this._bar=bar;
    }
    console.log(a(1,2)._foo);
</script>

使用new命令的基本原理:
首先先创建一个空对象,作为要返回的实例对象,其次将这个空对象,指向prototype属性,接着将空对象指向函数内部的this变量,最后开始执行构造函数
而在构造函数中有return的时候,如果return后面跟着一个对象,使用new命令调用的时候,就会返回该对象,否则就会返回this指向的对象
在这里插入图片描述
而在函数中如果没有使用this却使用new命令调用,该函数就相当于是一个普通函数,使用new命令调用,就会返回一个空对象
new命令简化流程
在这里插入图片描述
new.target 属性
如果一个函数使用了new命令,用new.target就会返回该函数,否则就会返回undefined,利用这一方法,可以判断函数中是否使用new命令

<script>
    function f(){
        if(!(new.target)){
            return "请使用new命令调用";
        }
    }
    console.log(f());
</script>

object.create()
以某个实例为模板,生成另一个实例

在这里插入图片描述

this

this的使用场合:
有三种
1:this可以指向全局变量window
在这里插入图片描述
2:this可以在构造函数中使用,指向对象
在这里插入图片描述
3:适用于对象的方法中
将A对象的方法赋给B对象,在这个过程中this指向也会从A转为B
在这里插入图片描述
在逻辑运算符中,||运算符,如果||前面为false,那么就会返回后面这个元素的值,如果||前面为true,那么就会返回||前面的值
this中的注意点
1:避免第二层使用this
例如:

var o={
        f1:function(){
            console.log(this);
           var f2=function(){
               console.log(this);
           }();
        }
    };
    o.f1();

这个例子中两层函数中都是用了this,而第一个返回object,第二个则返回window,说明第一个this指向对象,而第二个函数则指向了全局变量
而如果将代码改一下,引入一个中间值

var o={
        f1:function(){
            console.log(this);
            var  that=this;
           var f2=function(){
               console.log(that );
           }();
        }
    };
    o.f1();

则返回的结果都是object,因为赋值给that的this变量是指向外层this的,而在JS严格模式下,当函数中的this变量指向全局变量的时候,就会报错
2:数组处理方法中的map。forEach方法中的this调用时,也要注意this的指向
案例:
var o={

       v:"hello",
       p:["a1","a2"],
       f:function (){
           this.p.forEach(function(item){
              console.log(this.v+" "+item);
           });
       }
   }   

forEach遍历中的this指向的是全局变量,内部函数中的this是没有办法指向外部的,所以办法拿到o.v,就会返回undefined
如果修改一下代码:

var o={
       v:"hello",
       p:["a1","a2"],
       f:function (){
           var that=this;
           that.p.forEach(function(item){
              console.log(that.v+" "+item);
           });
       }

   }

此时就会返回 hello a1 hello a2
还有一种方法处理,就是将this写成是forEach的第二个参数

var o={
       v:"hello",
       p:["a1","a2"],
       f:function (){
           this.p.forEach(function(item){
               console.log(this.v+" "+item);
           },this);
       }

   }
   o.f();

就会返回 hello a1 hello a2
绑定this的方法
绑定this的方法有三种
1:function.prototype.call()
指定函数内部的this指向,
在这里插入图片描述
一般情况下,括号里面如果是空,null或者是undefined,this默认指向全局变量:window
call的第一个参数是this指向的参数,后面的参数是函数调用过程中需要用到的参数,一般在应用中,call方法用于调用对象的原生方法之中。
2:function.prototype.apply();
apply方法和call方法很相似,唯一的区别是,apply可以使用数组来调用函数的参数,第一个参数是this指向的参数,第二个参数是由存放有函数调用需要的参数组成数组
应用:
找出数组中的最大元素:使用MAth方法和apply的方法相结合 Math.Max.apply();
将一个数组中的空对象转化为undefined:空元素与undefined的差别在于,数组的forEach方法会跳过空元素,但是不会跳过undefined。因此,遍历内部元素的时候,会得到不同的结果。
转换类似数组对象:上面代码的apply方法的参数都是对象,但是返回结果都是数组,这个方法起作用的前提是,被处理的对象必须有length属性,以及相对应的数字键。
绑定回调函数对象
3:functio.prototype.bind();
bind方法用于将函数体内的this绑定到某个对象,然后返回一个新函数。
bind比call和apply更先进的一步是除了可以调用this关键字之外,还可以调用函数自身的参数
在这里插入图片描述
如果bind的第一个参数是null或者是undefined,就表示说this指向全局变量
bind的一些注意事项
1:每次返回一个新的函数,监听事件的时候,不能写成下面这样。element.addEventListener(‘click’, o.m.bind(o));
click事件绑定bind方法生成的一个匿名函数。这样会导致无法取消绑定,正确的是var listener = o.m.bind(o);
element.addEventListener(‘click’, listener);
// …
element.removeEventListener(‘click’, listener);
2:回调函数使用:回调函数是JavaScript最常用的模式之一,但是一个常见的错误是,将包含this的方法直接当作回调函数。还有一种情况比较隐蔽,就是某些数组方法可以接受一个函数当作参数。这些函数内部的this指向,很可能也会出错。
3:利用bind改写JS的原生方法适用形式
在这里插入图片描述
4:call和apply都是改变上下文中的this并立即执行这个函数,bind方法可以让对应的函数想什么时候调就什么时候调用,并且可以将参数在执行的时候添加,这是它们的区别

发布了35 篇原创文章 · 获赞 5 · 访问量 829

猜你喜欢

转载自blog.csdn.net/weixin_43332220/article/details/100777392