JS笔记——函数中的this引用

JavaScript中级
在javascript的函数中,除了函数声明时定义的形参之外,每个函数还可以接收另一个隐藏的参数:this,又称this引用。
this引用是一种在js代码中随时都可以使用的只读变量.
this的值(即它的指向)取决于调用的方式。

在javascript中this指向大致有四种情况:
1 、无任何前缀的函数调用时,this指向顶层对象或者叫全局对象,浏览器里是window(nodejs里是global)。

function fn(){
    console.log(this);
}
fn();                //打印结果为window{...}

2 、方法调用的时候,this指向方法所在的对象

var robot = {
            name:"cup",
            say:function(){
                   console.log(this.name)
                }
            };
robot.say();        //打印结果为'cup'

3 、构造函数里,this指向新生成的实例

function Robot(name){
    this.name = name;
    this.say = function(){
                console.log(this.name)
             }
}
var robot_1 = new Robot('bower');
robot_1.say()        //  打印结果为'bower'
var robot_2 = new Robot('cup');
robot_2.say()        //  打印结果为'cup'

4 、apply/call调用的时候,this指向apply/call方法中的第一个参数

var robot_1 = {name:'cup'}
var robot_2 = {name:'bower'}
function say(){
  console.log(this.name)
}
say.call(robot_1)     //  打印结果为'cup'
say.call(robot_2)     //  打印结果为'bower'

apply/call是js语法中一种特殊用法,两者的用法十分相似。

函数的apply与call方法
所有的函数都默认包含apply和call这两种方法,调用函数的apply或call方法,就相当于调用该函数。而apply和call的功能是,通过传参的方式,强制函数内的this指定某一对象。this引用的会被指向apply/call的第一个参数。

var robot_1 ={ name:"cup", say:function(){
                        console.log(this.name)
                        }
              };
var robot_2 ={ name:"bower" };
robot1.say() //打印结果为cup
robot_1.say.apply(robot_2)            // 打印结果为bower
//通过apply调用robot_1.say方法。方法内的this引用引用了robot_2
robot_1.say.call(robot_2)                // 打印结果为bower
//通过call调用robot_1.say方法。方法内的this引用引用了robot_2

apply与call之间的不同之处在于两者对其他参数的传递方式。

  • 对于apply来说,剩余的参数将通过数组来传递
  • call是直接按参数列表传递
function say(age, gender){console.log("My name is " + this.name + ",I'm a " + age + " years old " + gender + ".")}

say.apply({name:"cup"}, [12, "boy"])   
 //打印结果为 My name is cup,I'm a 12 years old boy.
// this.name = "cup", age = 12, gender = "boy"  作为第二个参数的数组中的元素都是函数say的参数,按顺序依次对应

say.call({name:"cup"}, 12, "boy")    
//打印结果为 My name is cup,I'm a 12 years old boy.
// this.name = "cup", age = 12, gender = "boy"  从第二个参数起的参数都是函数say的参数,按顺序依次对应

在实际的编程过程中,我们有时会为了函数回调而使用apply或call调用。

关于方法和this引用的具体例子解析:

1 、方法内的this调用

//对象定义
var robot = {
    name : "cup",
    say : function() { console.log( "Hi, I'm " + this.name + "."); }
}
robot.say()            // 打印结果为 Hi, I'm cup.
//对象robot是被调用的对象,say是方法。

上面的例子:首先是将对象赋给了变量robot。这个对象有两个属性。属性name的值为"cup",属性say的值是一个函数。该函数称作say方法。 被调用的方法say内的关键字this引用指向了被调用的对象robot。

2 、函数内的this调用

如果将含有this的对象方法取出来单独执行

var robot = {
    name : "cup",
    say : function() { console.log( "Hi, I'm " + this.name + "."); }
}
var fn = robot.say;
// 将robot.say引用的函数赋值给全局变量 fn.
fn()                        // 打印结果为 Hi, I'm .
// 执行函数(全局的方法),this引用了全局对象,由于全局对象没有name属性,所以没有取到值.

根据我们之前讲的,现在这个函数由于是无任何前缀的直接调用的,this应该是指向了全局对象,我们确认一下this是否指向了全局对象

var robot = {
    name : "cup",
    say : function() { console.log( "Hi, I'm " + this.name + "."); }
}
var fn = robot.say; //将robot.say引用的函数赋值给全局变量 fn.
//相当于给全局对象定义了一个属性fn,并赋予robot.say所指代的函数.

var name = "bower",
//相当于给全局对象定义了一个属性name,赋值为"bower",在浏览器里,上面这行代码等价于 window.name = "bower";

fn()                    // 打印结果为 Hi, I'm bower.
//执行函数fn(相当于调用全局对象的fn方法),执行时this引用了全局对象.所以this.name的值是"bower".

一个典型的定义类的方法

function Car(x,y){ 
    this.x = x;
    this.y = y;
    this.run = function(x_increase, y_increase){
        this.x += x_increase;
        this.y += y_increase;
    }
    this.show = function(){
        console.log("( " + this.x + "," + this.y + " )");
    }
}

通过上述代码,我们就拥有了一个名为Car的“类”。它有两个成员变量x和y还有一个成员函数run。那么我们就可以像用Object一样使用它:

var a_car = new Car(2,4); //获得了一个坐标为(2,4)的Car对象,x为2,y为9
a_car.run(10,5);          //a_car.x变成了12,a_car.y变成了9
a_car.show();             //打印结果为 ( 12,9 )

当我们使用new Car(2,4)的时候,就会生成一个对象,在调用的过程中会调用所谓的构造函数。而在本页第一段代码中的Car函数就是一个构造函数。
它既是一个类,又是一个构造函数, 严格的讲,它应该是相当于一个类。

使用这种方式去自定义类,所有的成员定义都放在构造函数里,不论函数还是属性。这样做的话,每次构造一个对象,都要对所有的函数重新分配内存。 比如

var a_car = new Car(2,4);
var b_car = new Car(3,3);
上面的代码new了两次,相应的run和show被分配了两次内存。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容

  • 1. this之谜 在JavaScript中,this是当前执行函数的上下文。因为JavaScript有4种不同的...
    百里少龙阅读 979评论 0 3
  • title: js面向对象date: 2017年8月17日 18:58:05updated: 2017年8月27日...
    lu900618阅读 553评论 0 2
  • 第5章 引用类型(返回首页) 本章内容 使用对象 创建并操作数组 理解基本的JavaScript类型 使用基本类型...
    大学一百阅读 3,196评论 0 4
  • 导语 不得不说,作为一名初级的前端开发者,this关键字这个问题对于我来说一直是一个痛点,什么是this?什么是函...
    Nicole_tiny阅读 522评论 0 4
  • 我还是没有听从班主任的,劝告。说交通这么发达,你娘家可以远一点事实上,我还是选成了现在的样子没有对错我就是我的样子...
    lygly9阅读 172评论 0 0