前言 本篇文章将讲到之前new原理中的为讲到的call()方法
this 提供了一种更优雅的方式来隐式的传递一个对象的引用,可以让代码更加简洁利于复用
//需要给speek和identify显示传入一个上下文对象 function identfy(context) { return context.name.toUpperCase(); //英文大写 } function speak(context) { var greeting = "hello ,I'm " + identfy(context) + ",I hate Trump!"; console.log(greeting); } var me = { name: "", }; speak(me); function identfy1() { return this.name.toUpperCase(); // toUpperCase(); //英文大写 } function speak1() { var greeting = "hello ,I'm " + identfy1.call(this) + ",I love China!"; console.log(greeting); } var me1 = { name: "Donald Trump", }; speak1.call(me1); //调用的时候
函数作用域:全局作用域:默认this指向的是window
块级作用域?不不没有它,只有上面两个,为什么?
//块级 { let a = this; console.log(a); }
来,你看这段代码,块级作用域是指let的变量和{}一起是块级,那么这this就不是在块级里面了,实则是在全局window上哦
this是一个代词,它代指一个对象
1.默认绑定---当函数 被独立调用时 ,函数的this默认指向到window (即使this是在函数体里的,但是被独立调用,仍然会指向全局的window)
// 代指: var a = 1; //挂在window function foo() { console.log(this.a);//this是在foo里面的,但它指向的是window } function Bar() { var a = 2; foo();//独立调用 } Bar();
要在浏览器上才能看到挂在windowd的上的a,编译器上运行node结果是undefined,所以后续要用到window全局的,代码都在浏览器上执行
独立调用是什么?没有其他前缀的调用
var obj = { a: 1 , foo: function () { console.log(this); }//不是独立调用 }; obj.foo();
这段代码就不是独立调用 有obj去调用它
在来看下面这段代码:同理因为是独立调用触发的是默认绑定,绑定在window,全局上,所以this是函数作用域外面的全局作用域
2.隐式绑定---当函数引用有上下文对象且被该对象调用时,隐式绑定规则会把函数调用中的this绑定到这个上下文对象 什么是函数引用 是指foo()不带() 的 foo
var a = 1; function foo() { console.log(this.a); } var obj = { a: 2, foo: function () { console.log(this.a); }, }; obj.foo(); var obj = { a: 2, foo: foo, //foo引用 来找找到函数 }; obj.foo(); var obj = { a: 2, foo: foo(), }; obj.foo(); //报错 obj.foo
第一个obj与第二个obj是等同的,单写foo是指引用,v8执行时会去找foo变量或者函数,这里没有变量就会找到函数foo
第三种写法是错误的,foo()加了括号这里就是调用函数,而这里的函数没有返回值,这里的值就是undefin,那么foo:undefined
,而后在对象外面调用的话,obj.foo(),是调用名为foo的函数,但这里foo:undefined
值是undefined不是函数体,所以会报错,如果是obj.foo的话是指对象的一个属性,属性名为foo,并且这里没有做任何操作,也不会报错。
3.隐式丢失---当一个函数被多层对象调用时,函数的this会指向最近的那一层对象
var a = 1; function foo() { console.log(this.a); } var obj = { a: 2, foo: foo, //foo引用 }; var obj2 = { a: 3, obj:obj }; obj2.obj.foo();
函数的this会指向最近的那一层对象即obj而不是obj2
4.显示绑定
1.fn.call(obj,x,y,....)显示的将fn里面的this绑定到obj对象上,并且call帮fn接收参数
function foo(x,y){ console.log(this.a,x+y); } var obj={ a:2 } foo.call(obj,1,2)//显示绑定 foo.call(1,1,2)//如果第一个参数不是对象,默认给一个null foo.call(null,1,2)//显示绑定
call方法是定义在Funtion.prototype上的foo.prototype.__proto__===Function.prototype
call将this指向obj ,并且帮忙接收foo参数和调用foo函数
2.fn.apply(obj,[x,y,....])显示的将fn里面的this绑定到obj对象上,并且apply帮fn接收参数,参数必须以数 组的形式盛放
foo.apply(obj,[1,2])//区别
3.fn.bind(obj,x,y,....)(x,x, ....)显示的将fn里面的this绑定到obj对象上,并且bind会返回一个新的函数,bind和新函数都可以负责帮fn接收参数,参数零散的传入
const bar=foo.bind(obj,1,2)// bar() const bar1=foo.bind(obj) bar1(1,2) const bar3=foo.bind(obj,2,4) bar3(1)
bind会返回一个新的函数体,但是我们要自己触发这个函数,才能接着触发foo的函数
5.new绑定 --new 的原理会导致函数的this绑定到实例对象上
function Person() { //var obj = {}; //Person.call(obj); this.name = "特朗普"; this.age = 18; console.log(this); //obj.__proto__ = Person.prototype; //return obj; } const p1 = new Person();
因为new的过程使用了call()方法将将Person的this指向obj,最后将obj返回给实例对象,即即把Person的this绑定到了实例对象上
箭头函数中没有this这个概念,写在了箭头函数的中的this,也是它外层那个非箭头函数的this
function a() { console.log(this); let b = function () { let c = () => { let d = () => { console.log(this);//箭头函数里面没有this这个关键字 }; d(); }; c(); }; b(); } a();
这的this是在fuction a(){} 里面的,但不指向funtion a(){},因为默认绑定规则,所以是指向window的
var a = 1 var obj = { a: 2, bar: function() { const baz = () => { console.log(this.a); } baz() } } obj.bar()
如有错误欢迎指正,欢迎各位友友评论点赞!
有话要说...