《JavaScript设计模式与开发》笔记 3.call和apply
Posted SmarTom
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《JavaScript设计模式与开发》笔记 3.call和apply相关的知识,希望对你有一定的参考价值。
- 1.改变this指向
- 2.Function.prototype.bind
- 3.借用其他对象方法
- 1.借用实现继承
- 2.实现恶心的
- Array.prototype.push.call
- Array.prototype.join.call
- Array.prototype.slice.call
- Object.prototype.toString.call
1.改变this指向
var obj1 = { name:"Bob marley" }; var obj2 = { name:"Bob Dylan" }; var name = "David Bowie"; var getName = function(){ console.log(this.name); } getName(); //输出undefined getName.call(obj1); //输出Bob marley getName.call(obj2); //输出Bob Dylan
在实际开发中,经常会遇到this指向被不经意改变的场景:例如:
document.getElementById(‘div1‘).onclick=function(){ alert(this.id); //输出div1 var func = function(){ alert(this.id); //输出undefined } func(); };
使用call来修复func函数内的this,使其指向div
document.getElementById(‘div1‘).onclick=function(){ alert(this.id); var func = function(){ alert(this.id); } func.call(this); }; 再如: var name = "SmarTom"; var func = function(){ console.log(this.name); } func();
使用call来修复func函数内的this,使其指向div 再如:
var obj ={ name : "SmarTom" } var func = function(){ console.log(this.name); } func.call(obj);
2.Function.prototype.bind
大部分浏览器都实现了内置的Function.prototype.bind,用来指定函数内部的this指向 即使没有原生的Function.prototype.bind实现,也可以模拟一下,例如:
//在一些浏览器中可以忽略 bind函数
Function.prototype.bind = function(context){ var _self = this; return function(){ return _self.apply(context,arguments); } } var obj = { name :"SmarTom" } var func = function(){ console.log(this.name); }.bind(obj); //进行绑定 func();
3.借用其他对象的方法【实现继承】
1.借用实现继承
var A = function(name){ //父类 A this.name = name; } var B = function(){ //子类 B 继承父类A A.apply(this,arguments); } B.prototype.getName = function(){ //B方法 return this.name; } var b = new B(‘asdfasdfasdf‘); console.log(b.getName());
2.实现
Array.prototype.push.call Array.prototype.join.call Array.prototype.slice.call Object.prototype.toString.call() 1. Array.prototype.push.call Array.prototype.push.call(obj,arguments) 相当于var html = []; html.push(那一大堆) <script type="text/javascript"> (function () { var customService = function () { }; customService.prototype = { open: function () { contents: this._getHtml(), }, close: function () { }, _getHtml: function () { var html = []; Array.prototype.push.call(html, ‘<div class=\"content\">‘, ‘<div>1、</div>‘, ‘<div>2、<\/div>‘, ‘<div>3、<\/div>‘, ‘<div>4、<\/div>‘, ‘<\/div>‘ ); return html.join(‘‘); } }; window.CustomService = new customService(); })(); </script> 2.Array.prototype.join.call //arguments就相当于一个对象数组 Array.prototype.join.call(arguments,‘,‘) 就类似于window.join方法.apply,call不会改变scope,可参考finally里的内容 <script type="text/javascript"> var join = function () { for (var i = 0, b = ‘‘; i < this.length ; i ++) { if (i) b+= arguments[0]; b += this[i]; } return b; }; var show = function () { //new Array(arguments)).join(‘_‘); //try try { alert( Array.apply(null, arguments).join(‘_‘) ); return join.call(arguments, ‘-‘); //Array.prototype.join就类似于window.join方法.apply,call不会改变scope,可参考finally里的内容 } finally { var func = function () { alert(a); }; void function () { var a = 1; try { func.call(this); } catch (exp) { alert(exp.message); } }(); } }; alert(show(1, 2, 3, 5)); </script> 3.Array.prototype.slice.call var a={length:2,0:‘first‘,1:‘second‘}; Array.prototype.slice.call(a);// ["first", "second"] var a={length:2}; Array.prototype.slice.call(a);// [undefined, undefined] 可能刚开始学习js的童鞋并不是很能理解这句为什么能实现这样的功能。 比如我就是一个,所以,来探究一下。 首先,slice有两个用法,一个是String.slice,一个是Array.slice, 第一个返回的是字符串,第二个返回的是数组,这里我们看第2个。 Array.prototype.slice.call(arguments)能够将arguments转成数组,那么就是arguments.toArray().slice(); 到这里,是不是就可以说Array.prototype.slice.call(arguments)的过程就是先将传入进来的第一个参数转为数组,再调用slice? 4.Object.prototype.toString.call 使用Object.prototype上的原生toString()方法判断数据类型,使用方法如下: Object.prototype.toString.call(value) 1.判断基本类型: Object.prototype.toString.call(null);//”[object Null]” Object.prototype.toString.call(undefined);//”[object Undefined]” Object.prototype.toString.call(“abc”);//”[object String]” Object.prototype.toString.call(123);//”[object Number]” Object.prototype.toString.call(true);//”[object Boolean]” 2.判断原生引用类型: 函数类型 Function fn(){console.log(“test”);} Object.prototype.toString.call(fn);//”[object Function]” 日期类型 var date = new Date(); Object.prototype.toString.call(date);//”[object Date]” 数组类型 var arr = [1,2,3]; Object.prototype.toString.call(arr);//”[object Array]” 正则表达式 var reg = /[hbc]at/gi; Object.prototype.toString.call(arr);//”[object Array]” 自定义类型 function Person(name, age) { this.name = name; this.age = age; } var person = new Person("Rose", 18); Object.prototype.toString.call(arr); //”[object Object]” 很明显这种方法不能准确判断person是Person类的实例,而只能用instanceof 操作符来进行判断,如下所示: console.log(person instanceof Person);//输出结果为true 3.判断原生JSON对象: var isNativeJSON = window.JSON && Object.prototype.toString.call(JSON); console.log(isNativeJSON);//输出结果为”[object JSON]”说明JSON是原生的,否则不是; 注意:Object.prototype.toString()本身是允许被修改的,而我们目前所讨论的关于 Object.prototype.toString()这个方法的应用都是假设toString()方法未被修改为前提的。
以上是关于《JavaScript设计模式与开发》笔记 3.call和apply的主要内容,如果未能解决你的问题,请参考以下文章
JavaScript设计模式与开发实践---读书笔记 迭代器模式