javascript设计模式学习之二——this
一、this指向问题
1)默认绑定,即作为独立的普通函数调用
此时this指向全局对象window,如果是严格模式下,则指向undefined;
2)隐式绑定,即具有调用上下文(一种场景就是作为对象的属性调用)
隐式绑定会将this绑定到这个上下文对象,如obj.getA();this就指向.之前的函数调用者;对象属性引用链中只有上一层或者说最后一层在调用位置中起作用。如obj1.obj2.foo(),调用时this指向obj2;
隐式绑定常见的问题就是隐式绑定的函数会丢失绑定对象。这点在第二部分会详细介绍。
3)显式绑定,
通过call/apply指定上下文对象。事实上ES5提供了内置方法Function.prototype.bind,也可以达到类似的效果。
4)new构造调用
事实上javascript中并不存在所谓的“构造函数”,只有对函数的“构造调用”。在javascript中,构造函数只是一些使用new操作符时被调用的普通函数,它们不会属于某个类,也不会实例化一个类。当使用new运算符调用函数时,该函数会返回一个对象,构造器中的this就指向返回的这个对象;需要注意的是,如果构造器显式返回了一个object类型的对象,那么此次运算结果最终会返回这个对象,构造器中的this也会指向这个对象,而非我们期望的this;
下面是自己实现的new(没有考虑构造函数待参数的情况,如果需要考虑,加一个参数即可)
var myNew = function(func) {
var o = Object.create(func.prototype);
var k = func.call(o);
if (typeof k === 'object') {
return k;
} else {
return o;
}
}
5)this绑定的优先级:
a:函数是否在new中调用?如果是的话this绑定的是新创建的对象;
b:函数是否通过call,apply显示绑定?如果是的话,this绑定的是指定的对象;
c:函数是否在某个上下文对象中调用(隐式绑定)?如果是的话,this绑定的是指定的对象;
d:如果都不是得花,使用默认绑定,在非严格模式下,绑定到全局对象window;在严格模式下绑定到undefined.
二、隐式绑定中的this丢失问题
思考下面一个问题,在prototype.js等框架中,做过这样的事情:
var getId=function(id){
return document.getElementById(id);
}
var oDiv=getId('div1');
思考为什么不用下面更简单的方式:
var getId=document.getElementById;
var oDiv=getId('div1');
后者会抛出一个异常,这是因为许多引擎的document.getElementById方法的内部会用到this;这个this被期望指向document,当getElementById被作为方法调用的时候,this指向没有问题;但是当用getId来引用documant.lgetElementById的时候,就成了普通函数的调用,因为getId引用的只是getElementById函数本身,其函数内部的this指向了window,而不是期望的doucment;
可以尝试利用下面的方法进行this修正(显式绑定)
document.getElementById=(function(func){
return function(){
func.apply(document,arguments);
}
})(document.getElementById);
var getId=document.getElementById;
var div=getId('div1');
三、显示绑定:call和apply
1.这两个函数可以指定this的指向,apply使用数组或者类数组作为参数,call则参数数量不固定,从这个意义来说,apply比call使用的频率更高;如果传入的首个参数是null,则代表作为普通函数调用,this此时指向window;
2.这两个函数在某些场合下使用的目的不在于指向this,而是用于借用其他对象的方法;比如类数组如arguments添加数据可以借用[].prototype.push.call;转换为真正的数组可以采用[].prototype.slice.call;截取收元素可以借用[].prototype.shift.call;能够借用的关键在于这些函数内部实现原理同样也可适用于类数组的对象;只要满足以下条件:
1)对象本身可以通过数字下标存取属性;
2)对象的length属性可以读写;
jQuery框架中的$对象设计成类数组,其思想大概也是由此而来的吧。
3 值得注意的是,如果把null或者undefined作为this的绑定对象传入call,apply或者bind,这些值在调用的时候回被忽略,实际应用的是默认绑定规则。
这在借用其他对象的方法时,会时常碰到这种用法。
此时可能产生一些副作用,如果某个函数确实应用了this,就有可能修改全局对象,带来不可预料的后果。一种“更安全”的方法时,创建一个DMZ对象来替代null/undefined,在javascript创建一个空对象最简单的方法是object.create(null),object.create(null)和{}很像,但是不会创建prototype这个委托,因此比{}更空。
javascript设计模式学习之二——this的更多相关文章
- 设计模式学习(二十四):Spring 中使用到的设计模式
设计模式学习(二十四):Spring 中使用到的设计模式 作者:Grey 原文地址: 博客园:设计模式学习(二十四):Spring 中使用到的设计模式 CSDN:设计模式学习(二十四):Spring ...
- JavaScript设计模式学习之路——面向对象的思想
今天,我拿到了张容铭写的这本<JavaScript设计模式>这本书,开始了关于JavaScript更深一点的学习. 看到这本书开始的时候,虽然之前通过看书.一些比较好的视频的讲解,对Jav ...
- Javascript设计模式学习一
学习Javascript设计模式之前,需要先了解一些相关知识,面向对象的基础知识.this等重要概念,以及掌握一些函数式编程的技巧. Js多态 多态的思想:实际上是把“做什么”和“谁去做”分离开来.例 ...
- JavaScript正则表达式学习笔记(二) - 打怪升级
本文接上篇,基础部分相对薄弱的同学请移步<JavaScript正则表达式学习笔记(一) - 理论基础>.上文介绍了8种JavaScript正则表达式的属性,本文还会追加介绍几种JavaSc ...
- JavaScript设计模式学习笔记
1 JavaScript设计模式深入分析 私有属性和方法:函数有作用域,在函数内用var 关键字声明的变量在外部无法访问,私有属性和方法本质就是你希望在对象外部无法访问的变量. 特权属性和方法:创建属 ...
- Java设计模式学习笔记(二) 简单工厂模式
前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 正文开始... 1. 简介 简单工厂模式不属于GoF23中设计模式之一,但在软件开发中应用也较为 ...
- JavaScript设计模式基础(二)
JavaScript 设计模式基础(一) 原型模式 在以类为中心的面向对象编程语言中,类和对象的关系就像铸模和铸件的关系,对象总是从类中创建.而原型编程中,类不是必须的,对象未必从类中创建而来,可以拷 ...
- JavaScript 基础学习(二)js 和 html 的结合方式
第一种 使用一个标签 <script type="text/javascript"> js代码; </script> 第二种 使用 script 标签,引入 ...
- JavaScript 基础 学习 (二)
JavaScript 基础 学习 节点属性 每一个节点都有自己的特点 这个节点属性就记录着属于自己节点的特点 1. nodeType(以一个数字来表示这个节点类型) 语法:节点.nodeT ...
随机推荐
- tomcat从下载到使用
话说,某天正在和周公聊天下大事.被急促的电话铃声召唤回来,所谓江湖救急,于是远程一看.竟然是需要使用tomcat(汤姆家的猫),于是... 下面关于下载和配置tomcat的过程. ①.使用tomcat ...
- iOS coreData使用遇到的问题
使用coreData,一定要有上下文环境.创建上下文时,和以前有些不同,之前 NSManagedObjeContext *context = [NSManagedObjectContext alloc ...
- jquery CDN(内容分发网络)使用
jquery CDN 给开发者提供一种捷径,即不下载jquary 就通过CDN能使用各个版本的jquery. 使用方法很简单,就是在HTML 文档中引用相关版本的jquery. 例如:我用百度的CDN ...
- 2016.07.14,英语,《Vocabulary Builder》Unit 25
verb: comes from the Latin verbum, meaning 'word'. verbally: ['vɜːbəli] adv. 口头地,词句地, 逐字地 verbalize: ...
- mysql读写分离(PHP类)
mysql读写分离(PHP类) 博客分类: php mysql 自己实现了php的读写分离,并且不用修改程序 优点:实现了读写分离,不依赖服务器硬件配置,并且都是可以配置read服务器,无限扩展 ...
- 20145235 《Java程序设计》第6周学习总结
教材学习内容总结 10.1 InputStream与OutputStream 串流设计的概念 Java将输入/输出抽象化为串流,数据有来源及目的地,衔接两者的是串流对象. 从应用程序角度来看,如果要将 ...
- [转]通过Mesos、Docker和Go,使用300行代码创建一个分布式系统
http://www.csdn.net/article/2015-07-31/2825348 [编者按]时下,对于大部分IT玩家来说,Docker和Mesos都是熟悉和陌生的:熟悉在于这两个词无疑已成 ...
- session配置理解
session.cache_limiter 指定会话页面所使用的缓冲控制方法,默认为nocache.session.cache_expire 以分钟数指定缓冲的会话页面的存活期,默认为180.此设定对 ...
- Artificial Intelligence Research Methodologies 人工智能研究方法
Computer Science An Overview _J. Glenn Brookshear _11th Edition To appreciate the field of artificia ...
- Java管道流
管道流的主要作用可以用于两个线程之间的通信,有管道输出流 PipeOutputStream和管道输入流 PipeInputStream.然后通过connect将两个管道连接起来. import jav ...