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 ...
随机推荐
- HDU 1166敌兵布阵+NOJv2 1025: Hkhv love spent money(线段树单点更新区间查询)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- 【翻译】CEDEC2015 速成Albedo Chart 制作
关于pbr材质和贴图的制作,最近llegorithmic提供了几篇不错的guide https://www.allegorithmic.com/pbr-guide 不过像如何从通过现实场 ...
- iconv vs mb_convert_encoding
iconv 字符串按要求的字符编码来转换 string iconv ( string $in_charset , string $out_charset , string $str ) 将字符串 st ...
- MongoDB性能监控
1.mongostat 查看运行中的mongodb实例的统计信息 重要指标说明: getmore: 通常发生在结果集比较大的查询时,第一个query返回了部分结果,后续的结果是通过getmore来获取 ...
- Apache(Web)服务器性能调整
Apache多路处理模块---MPM apache通过不同的MPM运行在多进程和多线程混合模式下,增强配置扩充性能.MPM无法模块化,只能在编译配置时选择,被静态编译到服务器中.目前apache版本中 ...
- 如何解决php 生成验证码图片不显示问题
最近遇到一个问题,就是验证码在别人的电脑上可以显示,但是我自己的电脑上去不能.原因找了好久,哈哈,终于找到了!现在给大家分享一下: 程序: <?php $w = 80; //设置图片宽和高 $h ...
- 汇总10.4版本ArcGIS Server与ArcMap 安装+SDE+注册数据源(非破解)
文档参考了Server技术支持部各位前辈的总结文档. win10 + Server 10.4 + ArcMap 10.4 + Oracle instant client (32位 和 64位) 安装 ...
- 在fortran下进行openmp并行计算编程
最近写水动力的程序,体系太大,必须用并行才能算的动,无奈只好找了并行编程的资料学习了.我想我没有必要在博客里开一个什么并行编程的教程之类,因为网上到处都是,我就随手记点重要的笔记吧.这里主要是open ...
- spring容器IOC创建对象<二>
问题?spring是如何创建对象的?什么时候创建对象?有几种创建方式?测试对象是单例的还是多例的 ?对象的初始化和销毁? 下面的四大模块IOC的内容了!需要深刻理解 SpringIOC定义:把对象的创 ...
- 深入了解Windows句柄到底是什么
深入了解Windows句柄到底是什么 http://blog.csdn.net/wenzhou1219/article/details/17659485 总是有新入门的Windows程序员问我Wind ...