JavaScript函数this指向

全局this指向window

一般函数 this/严格模式this

function f1(){
return this;
};
f1() === window//true

//严格模式
function f2(){
'use strict'
return this;
};
f2() === undefined;

作为对象方法函数的this

//示例1:
var o = {
	prop:37,
	f:function(){
		console.log( this);
	}
};
o.f();//{prop: 37, f: ?} this是o;

//示例2:
var o = {
prop:37
};
function indeprndent(){
	console.log(this);
}
indeprndent();//this 是 window
o.f = indeprndent;
o.f();//this是o;
window.o.f();//this是o;

对象原型链上的this

var o = {
	f:function(){
		return this.a+this.b;
	}
};

var p = Object.create(o);
p.a =1;
p.b = 2;
p.f();//3

get set的this

function modulus(){
	console.log('modulus',this)
}

var o ={
	re:1,
	im:-1,
	get phase(){
		console.log('phase',this.re,this.im)
	}
}

Object.defineProperty(o,'modulus',{
	get:modulus,emumerable:true,configurable:true
})
console.log(o.phase,o.modulus);
//phase 1 -1
//modulus {re: 1, im: -1}

构造器中this

function c2(){
	this.a = 37;
	return {a:38};
};
var o = new c2();
console.log(o.a);//38 如果return 是对象,就返回return 的对象。(return 基本类型没关系)

function c2(){
this.a = 37;
this.b=99;
return {a:38};
};
var o = new c2();
console.log(o.b);//undefined 如果return 是对象,就返回return 的对象。(return 基本类型没关系)

function c2(){
this.a = 37;
this.b=99;
return 12;
};
var o = new c2();
console.log(o.b)// 99(return 基本类型没关系)

this指向总结

最近是谁调用,this就是谁。

更改this指向

call与apply都属于Function.prototype的一个方法,所以每个function实例都有call、apply、bind属性;
call()方法和apply(),bind()方法的作用相同:改变this指向。

call/apply

//示例1
function add(c,d){
	return this.a+this.b+c+d;
};
var o = {a:1,b:3};
add.call(o,5,7);//16
add.apply(o,[10,20]) //34

//示例2
function bar(){
	console.log(Object.prototype.toString.call(this));
};
bar.call('5');//[object String]

apply / call严格模式

非严格模式
第一个参数:对象(不是对象会转)
如果传入是null 或者 undefinde 就是window;
但是在严格模式下:
如果传入是null 或者 undefinde 就是null 或者 undefinde ;

call 和 apply区别

call 传参扁平

apply 用数组

bind

使用:ie9+

改变this

//示例1
function f(){
	return this.a;
};
var g = f.bind({a:'text'});
var o = {a:37,f:f,g:g}
console.log(o.f(),o.g())//37 "text"

//示例2
this.x = 9; //window.x
var module = {
	x:81,
	getX:function(){return this.x;}
}
module.getX(); //81
var getX = module.getX;//没有运行
getX(); //9 因为是window调用的,this指向window
var getX = module.getX(); //调用的是module 并且运行获得返回值
getX;//81
var boundGetX = getX.bind(module);//更换this
boundGetX(); //81

科里化

function add(a,b,c){
	return a+b+c;
}
var func = add.bind(null,100);
func(1,2);//103;100+1+2;
var func2 = func.bind(null,100);//调用之前的func
func2(10);//210;100+100+10

bind 与 new

function foo(){
	this.b = 100;
	return this.a;
}
var func = foo.bind({a:1});
func();//1
var c = new func();  
c//foo?{b: 100} //return 不是对象 就用this 作为返回值。忽略return

bind方法模拟

//是否存在bind,不存在就执行以下方法;
if(!Function.prototype.bind){
  //oThis bind的第一个参数
  Function.prototype.bind = function(oThis){
    //判断当前调用对象 是不是函数
    if(typeof this !== 'function'){
      //不是函数就报错
      throw new TypeError("不是函数啊!")
    };
    //将bind除了第一个参数外的参数转为数组(浅拷贝)
    var aArgs = Array.prototype.slice.call(arguments,1);
    fToBind = this;//指的调用的函数
    fNOP = function(){};//空函数,后期用来
    fBound = function(){
      return fToBind.apply(this instanceof fNOP?this:oThis,
        aArgs.concat(Array.prototype.slice.call(arguments))//把oThis对象参数加入到aArgs
      )
    };
    fNOP.prototype = this.prototype;//fNOP.prototype 换为调用对象prototype
    fBound.prototype = new fNOP();//fBound 原型归fNOP
    return fBound;
  }
}

arguments

foo.length//返回参数数量
arguments.length//返回实际传参数数量
arguments //类数组
arguments.callee //callee属性是一个指针,指向拥有这个 arguments 对象的函数

//示例
function foo(x,y,z){
	console.log('arguments',arguments.length);
	arguments[0] = 10;
	//返回实际传参数数量
	console.log('x',x);	
	arguments[2]=11;
	//参数z没传所以,没有[2]对应z,所以对z不造成影响
	console.log('arguments[2]',arguments[2]);
	console.log('z',z);
	console.log(x,y,z);
	arguments.callee === foo;
};

foo(1,2);
//arguments 2
//x 10
//z undefined
//10 2 undefined

arguments严格模式下:

arguments[0] 变成了一个参数,不会改变x的值
arguments.callee 也无法使用。

Object.prototype.toString.call()常见问题

为什么Array、String、Number、Boolean等不能直接调用toString()去判断数据类型?

因为Array、String、Number、Boolean、RegExp、Date等类型都重写了toString(),
如果直接调用则因为自身的原型对象上已有toString()方法,
就不会调用到Object原型对象上的toString()方法了。

为什么不能用Array.prototype.toString.call([1,3,4])去判断数据类型?

因为Array,Function,Date虽然是基于Object进行创建的,
但是他们继承的是Object.toString(),而不是Object.prototype.toString()。
这样子调用的就是Object.toString()。

可以直接Object.prototype.toString,不用call()?

通过call将Array的this上下文切换到Object,从而调用了Object.prototype.toString(),因此返回[object Function]。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值