JS:劫持(call apply bind)
劫持一般有三类:
1、黑客劫持网站,隐私数据,个人信息等
2、通过劫持重置系统内置函数
3、this的引用劫持
接下来主要介绍this的引用劫持;
*通过函数call apply bind也可以重置系统内置函数;
1、call
方法:就是调用所有者对象作为参数的方法,可以自定义接收者来调用函数
语法:call(this: Function, thisArg: any, ...argArray: any[]): any
实例:
var obj = {}; var arr = []; function fn(arg1,arg2) { console.log(this); }; fn.call(obj); //{} fn.call(arr); //[] fn.call(null); //window{...} fn.call(1); //Number {1} fn.call(false); //Boolean {false} fn.call(undefined); //window{...}
2、apply
方法:能劫持另外一个对象的方法,继承另外一个对象的属性
语法:apply(this: Function, thisArg: any, argArray?: any): any
Function.apply(obj,args)方法能接收两个参数,除了obj也可以是数组
实例:
var obj1 = { name: 'lili' }; function fn() { console.log(this); } fn.apply(obj1); //{name: 'lili'} fn.apply(1); //Number {1} fn.apply(true); //Boolean {true} fn.apply([]); //[] fn.apply(undefined); //window{...} fn.apply(); //window{...}
call() 和 apply() 之间的区别:
call()
方法分别接受参数。
apply()
方法接受数组形式的参数。
如果要使用数组而不是参数列表,则 apply()
方法非常方便。
3、bind
方法:简单来说就是将函数绑定到某个对象;
语法:bind(this: Function, thisArg: any, ...argArray: any[]): any
fn.bind(obj)==>obj.fn(),函数内的this指向obj
实例:
var obj = { name: 'jack' }; var obj1 = { name: 'lili', fn: function () { console.log(this); }.bind(obj), } obj1.fn(); //{name: 'jack'} obj1.fn.call(obj); //{name: 'jack'} obj1.fn.apply(obj); //{name: 'jack'}
call、apply
var obj = { name: 'lili' }; var obj2 = { age : 10 } var obj1 = { name: 'lili', fn: function () { console.log(this); } } obj1.fn(); //{name: 'lili', fn: ƒ} obj1.fn.call(obj); //{name: 'lili'} obj1.fn.apply(obj2); //{age: 10}
4、fn.call.call()方法
(1)
function fn () { console.log(1,this) } function fn2 () { console.log(2,this) } fn.call(fn2)
打印结果:
1 ƒ fn2 () { console.log(2,this) }
我们可以看到,虽然更换了调用对象,但是打印的还是1,但this已经指向了fn2
(2)
function fn () { console.log(1,this); } function fn2 () { console.log(2,this); } fn.call.call(fn2);
打印结果:
2 Window {window: Window, self: Window, document: document, name: '', location: Location, …}
*这个过程执行是从 call(fn2)开始的,把this指向fn2;
*call(fn2) 前面的this 改成了fn2 ,前面方法照常执行;
fn1.call.call 的主体(this)是 fn1.call, 所以fn1.call变成fn2
*call(fn2) 前面是fn1.call 改变this 后,fn1 变成了 fn2,所以接下来执行的就是 fn2.call()
总结:
当有两个或以上的call,在第二步时改变了this指向,无论有多少call(fn1.call....call(fn2)),都是相当于fn2