上一篇随笔讲解了构造函数、原型及原型链相关的知识,今天让我们一起来探讨另一个问题:this。

一     this 的指向

  1,  函数预编译过程中,this指向window

  我们在讲解函数预编译过程的时候提到,函数在将要被执行时,会在[[scope]]属性中插入一个AO对象,AO对象包含了函数的形参、函数内声明的变量及子函数。实际上AO对象还有两个属性:this和arguments

  arguments用来存储接下来函数执行过程中接受到的实参列表。this用来接受函数中没有被声明就被赋值的变量(未声明访问将报错)。可以简单的理解为JavaScript的一种容错机制。这里的this就指向window,所以我们才说未声明的变量将被升级成window的属性。

 function test(a,b){
c = 10;
console.log(arguments);
console.log(c === window.c);
}
test(1,2);
//Arguments{0:1,1:2;length:2,...} 类数组
//true

  2,  全局作用域里this指向window。

  JavaScript的执行环境就是window,所以在全局作用域里window === this。

 console.log(this === window);//true

  3,  obj.method() 方法中的this指向obj

  如果有对象调用方法,那么方法内的this将指向调用对象。

  如果没有对象调用方法,即函数(方法)空执行,这里面的this还是将指向window。

 var name =  'ru';
var obj = {
name:'ren',
method:function(){
console.log(this.name);
}
};
obj.method();//'ren'
var test = obj.method;
test();//'ru'

二   call/apply/bind

  可以改变函数内部this的指向。

  1,  call(myThisarg,agr1,arg2,...)

  call()方法使用一个指定的对象替代函数内原本的this。函数原有的参数依次添加在其后。如果第一个参数是null或者undefined,那么函数内部的this将不被改变。

 function Person(name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;
}
/*
function Student(name,age,sex,classes,num){
this.name = name;
this.age = age;
this.sex = sex;
this.classes = classes;
this.num = num;
}
这种写法当然能够实现我们的功能,但Student构造函数的功能完美涵盖了Person,我们是否可以在创建Student实例时调用Person以简化代码呢?当然
*/
function Student(name,age,sex,classes,num){
Person.call(this,name,age,sex);
this.classes = classes;
this.num = num;
}
var student = new Student(1,2,3,4,5);
console.log(student);//{name:1,age:2,sex:3,classes:4,num:5}
 var person = {
name : 'ren',
say : function(){
console.log(this.name);
}
};
var animal = {
name : 'dog'
};
person.say();//'ren'
animal.say();//Typerror:animal.say is not a function
//我们怎么才能让dog也能学ren一样说话呢?
person.say.call(animal);//'dog'

  2,  apply()

  apply()方法的功能和call()完全一样。只是apply以数组形式接受原函数的参数。

 var arr = [50,-1,-20,2,99,38];
//我们怎么拿到arr数组中最大或最小的那个数呢?你可能第一反应当然是数组的sort方法。但今天我们有一个使用更简单的方法!
Math.max.apply(null,arr);//
Math.min.apply(null,arr);//-20
//因为这里不涉及操作this的问题,所以第一个参数为null

  3,  bind()

  bind()方法使用方式和call()完全一样,但功能上有所差别。bind执行会返回一个函数,这个函数内部的this已被改变,等待在合适的时候被调用。

call和apply是在函数执行时改变其this的指向,而bind是先改变函数内的this指向,然后返回一个新的函数。

 var person = {
name : 'ren',
say : function (){
console.log(this.name);
}
};
var animal = {
name : 'dog'
};
person.say.call(animal);//'dog' 立即返回执行结果
var test = person.say.bind(animal); //返回一个函数
console.log(test);//fn
test();//'dog'

三     callee、caller

  1,callee

arguments的一个属性,指向函数本身。

一般用在立即执行函数的递归调用。因为立即执行函数会忽略函数名,所以在递归调用时可以用callee来解决。

 var factorial = (function(n){
if(n == 1){
return 1;
}else{
return n * arguments.callee(n - 1);
}
}(50));

  2,caller

函数的一个属性,指向执行时的父函数。全局执行时,fn.caller == null。好像并没有什么卵用?

  另外,这两个属性在严格模式下还不能使用。

四   ES5严格模式

  关于ES5的严格模式这里就不详细讲解了,有兴趣的同学可以去这里:

  https://www.cnblogs.com/snandy/p/3428171.html

JavaScript之深入对象(二)的更多相关文章

  1. javascript之BOM对象(二location对象)

    一.location对象提供和当前加载的文档相关的信息还有一些导航功能.location对象是window对象的属性,同时也是document对象的属性.window.location和documen ...

  2. Unit05: JavaScript对象概述 、 常用内置对象一 、 常用内置对象二 、 常用内置对象三

    Unit05: JavaScript对象概述 . 常用内置对象一 . 常用内置对象二 . 常用内置对象三 常用内置对象使用演示: <!DOCTYPE html> <html> ...

  3. 前端之JavaScript:JS之DOM对象二

    继续JS之DOM对象二 前面在JS之DOM中我们知道了属性操作,下面我们来了解一下节点操作.很重要!! 一.节点操作 创建节点:var ele_a = document.createElement(' ...

  4. 二、JavaScript语言--JS基础--JavaScript进阶篇--JavaScript内置对象

    1.什么事对象 JavaScript 中的所有事物都是对象,如:字符串.数值.数组.函数等,每个对象带有属性和方法. 对象的属性:反映该对象某些特定的性质的,如:字符串的长度.图像的长宽等: 对象的方 ...

  5. javascript (十二)对象二

    JavaScript 中的所有事物都是对象:字符串.数字.数组.日期,等等. 在 JavaScript 中,对象是拥有属性和方法的数据. 属性和方法 属性是与对象相关的值. 方法是能够在对象上执行的动 ...

  6. Javascript基础回顾 之(二) 作用域

    本来是要继续由浅入深表达式系列最后一篇的,但是最近团队突然就忙起来了,从来没有过的忙!不过喜欢表达式的朋友请放心,已经在写了:) 在工作当中发现大家对Javascript的一些基本原理普遍存在这里或者 ...

  7. javascript中的对象,原型,原型链和面向对象

    一.javascript中的属性.方法 1.首先,关于javascript中的函数/“方法”,说明两点: 1)如果访问的对象属性是一个函数,有些开发者容易认为该函数属于这个对象,因此把“属性访问”叫做 ...

  8. javascript中Date对象的应用——简易日历的实现

    × 目录 [1]效果 [2]HTML [3]CSS[4]JS 前面的话 简易日历作为javascript中Date对象的常见应用,用途较广泛.本文将详细说明简易日历的实现思路 效果演示 HTML说明 ...

  9. JavaScript学习04 对象

    JavaScript学习04 对象 默认对象 日期对象Date, 格式:日期对象名称=new Date([日期参数]) 日期参数: 1.省略(最常用): 2.英文-数值格式:月 日,公元年 [时:分: ...

  10. JavaScript学习笔记——对象知识点

    javascript对象的遍历.内存分布和封装特性 一.javascript对象遍历 1.javascript属性访问 对象.属性 对象[属性] //字符串格式 //javascript属性的访问方法 ...

随机推荐

  1. Python 列表深浅复制详解

    在文章<Python 数据类型>里边介绍了列表的用法,其中列表有个 copy() 方法,意思是复制一个相同的列表.例如 names = ["小明", "小红& ...

  2. Jetbrains好用的插件(经验总结)

    # Jetbrain好用的插件(经验总结) 笔者使用过idea,phpstorm,webstorm,pycharm和goland开发过项目,不得不说,Jetbrains的编辑器每一款都挺好用的,而且快 ...

  3. 优化Recorder H5录音:可边录边转码上传服务器,支持微信提供Android IOS Hybrid App源码

    Recorder H5 GitHub开源库随着支持功能的增多,音频转码处理效率渐渐的跟不上需求了,近期抽时间对音频转码部分进行了升级优化,以支持更多实用的功能. 另外IOS的Hybrid App也完成 ...

  4. JDBC、Tomcat为什么要破坏双亲委派模型?

    问题一:双亲委派模型是什么 如果一个类加载器收到了加载某个类的请求,则该类加载器并不会去加载该类,而是把这个请求委派给父类加载器,每一个层次的类加载器都是如此,因此所有的类加载请求最终都会传送到顶端的 ...

  5. python 39 socketserver 模块并发通信

    socketserver模块 socketserver模块实现一个服务端与多个客户端通信.是在socket的基础上进行了一层封装,底层还是调用的socket. socketserver干了两件事: 1 ...

  6. 通过Callable接口创建线程

    通过Callable接口创建线程 一.前言 Java中创建线程的方式有四中,前两种在前面我已经详细介绍过了(Runnable和Thread),不清楚的朋友们可看这里: Java多线程之线程的启动以及J ...

  7. Leetcode之二分法专题-167. 两数之和 II - 输入有序数组(Two Sum II - Input array is sorted)

    Leetcode之二分法专题-167. 两数之和 II - 输入有序数组(Two Sum II - Input array is sorted) 给定一个已按照升序排列 的有序数组,找到两个数使得它们 ...

  8. 吃货眼中的sqlalchemy外键和连表查询

    前言 使用数据库一个高效的操作是连表查询,一条查询语句能够查询到多个表的数据.在sqlalchem架构下的数据库连表查询更是十分方便.那么如何连表查询?以及数据库外键对连表查询有没有帮助呢?本篇文章就 ...

  9. Java微服务(二):服务消费者与提供者搭建

    本文接着上一篇写的<Java微服务(一):dubbo-admin控制台的使用>,上篇文章介绍了docker,zookeeper环境的安装,并参考dubbo官网演示了dubbo-admin控 ...

  10. js 数组方法的作用,各方法是否改变原有的数组

    不会改变原来数组的有: concat()---连接两个或更多的数组,并返回结果. every()---检测数组元素的每个元素是否都符合条件. some()---检测数组元素中是否有元素符合指定条件. ...