目 录CONTENT

文章目录

面向对象程序设计(番外篇)

Administrator
2020-07-24 / 0 评论 / 2 点赞 / 14204 阅读 / 13869 字

面向对象程序设计(番外篇)

前面的章节里面,我们已经学习过面向对象的基础,知道怎么去创建对象,以及对对象的属性的遍历 。同时还知道了一个新的关键字叫this。这个关键字使用的频率非常高,后面只要是接触对象或者是方法都会使用到这一个关键字

this关键字

this是一个任人打扮的小姑娘

this它是一个关键字,也是一个指针,具体指的是什么则要看这个关键字指向了谁,它指向了谁就指的是谁,现阶段而言我们可以把this看成是一个指针

对象中的this

我们之前在创建对象的的时候是使用了this的,现在就来具体的年一下这个this在对象中的应用

var name = "标哥哥";			//全局变量
var stu1 = {
  	name:"杨兰芳",
  	sayHello:function(){
        console.log("大家好,我叫"+this.name);
    }
};

在上面的代码里面,我们可以看到sayHello这个方法里有一个关键字this,那么这个里面的this指向的是谁呢??

我们之前很笼统的给同学们说一点就是this指向当前对象。关键问题又来了,这个当前对象是谁呢

  1. 在全局环境下面,this指向是window这个对象

image-20200508141610195

  1. 在自定义对象里面this指向当前调用这个方法的对象

image-20200508141819937

当前这个sayHello()的方法是被对象stu1在调用,所以this指的就是stu1

根据上面的第一个特点,全局环境的this是指向window这个特点,我要补充以下几个知识

之前在讲解变量的时候,我们告诉同学,全局变量使用var关键字来进行定义。其实全局变量还可以用另外一种方式去理解(就是使用面向对象的方式去理解)

在JavaScript里面,一切皆对象,所以我们可以这么理解,window就是浏览器的最高对象,所以的东西都在这个window下面,我们如果在全局环境下面定义变量,其实就是在window这个对象下面给它添加了一个属性

var userName = "标哥哥";

上面的代码是定义了一个全局变量,其实全局变量本质上面是经过下面的这个过程

window.userName = "标哥哥";

这就是为什么我可以通过this.name去拿到定义的全局变量name,因为在全局环境下面this是指向了window 的,所以this.name指的也就是window.name,而window.name就是全局变量name

this指向window相当于this.namewindow.namevar name的全局变量

?思考 :现在根据上面的特点,我们来思考下面的代码的结果是什么??

var name = "标哥哥";			//全局变量
var stu1 = {
  	name:"杨兰芳",
  	sayHello:function(){
        console.log("大家好,我叫"+this.name);
    }
};
stu1.sayHello();		//输出什么?			//杨兰芳
var s = stu1.sayHello;	//将这个方法赋值给另一个变量
s();			   //再去调用s这个方法			//标哥哥

首先要经过分析

var s = stu1.sayHello其实就相当于window.s = stu1.sayHello。接下开始调用

s()其实就相当于window.s()

根据我们之前的原则 ,对象方法里面的this是指向调用这个方法的对象的,现在这个方法是被window在调用,所以里面的this应该要指向window

构造函数里面的this

函数也叫方法,在面向对象的观点里在,函数就是方法

之前的时候,我们学过构造函数去创建对象,在构造函数里面也有this。它的this又指向了谁呢?

var userName = "标哥哥";

//这是一个全局的方法,所以相当于window.Person
/*
        window.Person = function(){

        }
        var Person = function(){

        }
    */
function Person() {
    console.log(this);
}

构造函数本质上面与普通是没有区别的,关键是看它的调用方式,如果使用new的关键字调用,则是构造方法调用

Person();		//本质上面就是window.Person()这种方式调用
//现在是window在调用Person方法,所以这个方法内部的this就指向了window

new Person();		//构造函数在调用,构造函数里面的this指向当前创建的这个对象

经过上面的两个章节以后,我们都this其实是可以发生改变的。现在我们就来看一下方法里面的this的转移问题

方法以不同的形式去调用,this的指向也就不一样。(上面已经讲了一个构造方法,现在还有没有其它的方法呢)

函数的不同调用形式决定this指向【重点】

刚刚我们通过构造函数改变了this的指向,其实还有函数还有另外的几种方式也可以调用

我们之前已经讲过很多种函数的调用方式了,现在回顾一下

  1. 方法名+()调用
  2. var 方法名 = function(){}() 立即调用
  3. +function(){}()立即调用
  4. new function(){} 构造函数调用

除了上面的四种方式以外,我还有另外的三种方式调用方法。这三种方式都可以改变this的指向

通过call来调用方法

通过方法名.call(this指向,...原来方法里在的参数)

var userName = "标哥哥全局变量";

function sayHello(str) {
    console.log(str);
    console.log(this.userName);
}

var stu1 = {
    userName: "杨兰芳"
};

var stu2 = {
    userName: "赵聪"
};

sayHello("普通调用");         //标哥哥   window.sayHello();     this指向window\

sayHello.call(window,"我在通过call去调用");

sayHello.call(stu1,"我现在也在通过call去调用");

sayHello.call(stu2,"我是stu2在调用sayHello的方法");
第一种现象 第二种现象
image-20200508151654911 image-20200508151833763

通过call的这种形式,我们可以手动的把这个方法this改变掉

通过apply来调用方法

这一种调用方式跟call的调用方式是一模一样的,唯一不同的区别就在于原来方法里面的参数

var userName = "标哥哥";

function sayHello(str1, str2) {
    console.log(str1);
    console.log(str2);
    console.log(this.userName);
}

var stu1 = {
    userName:"杨兰芳"
};
// sayHello("第一个参数","第二个参数")  以常规的方式去调用

// sayHello.call(stu1,"第一个参数","第二个参数");

//通过apply调用
sayHello.apply(stu1,["第一个参数","第二个参数"])

下面是call调用的图

image-20200508152952820

下面是apply调用的图

image-20200508153359769

callapply唯一的区别点就是在这个地方apply的参数要变成要变成一个数组

通过bind来调用函数

bind方法与上面的callapply的作用是一样的,都是用于调用方法的时候改变方法的this,但要是要注意,bind方法在调用的时候,它不会立即执行原来的方法,而是会返回一个新的方法名,通过新方法名再去调原来的方法

语法格式:Function.bind(thisArg:object,...原来函数的参数)

var userName = "张三";

function abc() {
    console.log(this.userName);
}
var stu = {
    userName: "蒋晓菁"
}

abc(); //张三

var def = abc.bind(stu);    //bind会返回一个新的方法,新的方法的this才是你bind的这个对象
def();              //这个def是通过abc.bind(stu)得到的,所以def里面的this指向的是stu

def方法是通过abc.bind(stu)得到的,所以def方法里面的this指向的是stu这个对象

刚刚上面执行的bind是一个没有参数的方法,如果这个方法有参数呢,那应该怎么写呢?

 var userName = "张三";

function abc(x, y) {
    console.log(arguments);
    console.log(this.userName, x, y);
}

var stu = {
    userName:"李四"
}

abc(10, 11);

var d =  abc.bind(stu,99,100);
d();

var e = abc.bind(stu,200);
e(300);

var f = abc.bind(stu);
f(500,501);

var g = abc.bind(stu,600,601);
g(602,603);		//最终的arguments会接收到4个参数
2

评论区