一、对this的产生原因分析和了解

  1. 1.this指的是函数运行时所在的环境(即调用的对象)。
  2. 2.JavaScript 语言之所以有this的设计,跟内存里面的数据结构有关系

二、this绑定详解

this 实际上是在函数被调用时发生的绑定,它指向什么地方完全取决于函数在哪里被调用。

1.默认绑定

  1. function foo(){
  2. var a = 1 ; //局部变量
  3. console.log(this.a);
  4. }
  5. var a = 10; //全局变量
  6. foo(); //window.foo()

2.隐性绑定

  1. var a = 10; //全局变量
  2. function foo(){
  3. var a = 1 ; //局部变量
  4. console.log(this.a);
  5. }
  6. var obj = {
  7. a : 20,
  8. foo : foo
  9. }
  10. obj.foo(); //window.obj.foo()

3.显示绑定apply,call,bind 这个三个函数都是改变this指向

  1. (1)call
  2. var box=document.getElementById('box')
  3. box.onclick = function(){
  4. console.log(this) //指向box元素
  5.   function boxFn(params1,params2,params3){
  6. console.log(this)
  7.   }
  8. boxFn()
  9. boxFn.call(this,1,2,3) //call改变this指向,将this指向box元素
  10. }
  1. (2)apply
  2. var applayObj1={
  3. name:'张三'
  4. }
  5. var applayObj={
  6. name:'李四',
  7. applayFun(param1,param2,param3){
  8. console.log(this.name)
  9. }
  10. }
  11. var applayfun2=applayObj.applayFun
  12. applayObj.applayFun() //window.applayObj.applayFun()
  13. applayfun2.apply(this,[1,2,3]) //window.applayfun2.apply(this,[1,2,3])
  14. applayfun2.apply(applayObj1,[1,2,3]) //window.applayfun2.apply(applayObj1,[1,2,3])
  1. (3)bind
  2. var title='全局title'
  3. var applayObj1={
  4. name:'张三'
  5. }
  6. var bindObj={
  7. title:'改变this',
  8. bindFun(){
  9. console.log(this)
  10. }
  11. }
  12. bindObj.bindFun()
  13. var aa=bindObj.bindFun
  14. aa()
  15. aa.bind(applayObj1)()

4.new 绑定

new出来的对象有以下新特性:

  1. (1)创建一个新对象。
  2. (2)把这个新对象的__proto__属性指向 原函数的prototype属性。(即继承原函数的原型)
  3. (3)将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象)
  4. (4)返回新对象。(底层运行机制return返回一个新对象)
  1. var blogA='123'
  2. function blog(){
  3. this.blogA='456'
  4. this.blogFn=function(){
  5. console.log(this.blogA)
  6. }
  7. }
  8. var newblogObj=new blog()
  9. newblogObj.blogFn()
  10. console.log(newblogObj)

三、箭头函数的this绑定

(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

  1. var a=12
  2. function foo(){
  3. this.a=13
  4. return ()=>{
  5. console.log(this.a)
  6. }
  7. }
  8. let newFoo=new foo()
  9. newFoo()
  10. var b='666'
  11. function foo2(){
  12. console.log(this)
  13. return ()=>{
  14. console.log(this.b)
  15. }
  16. }
  17. var baz=foo2()
  18. baz();

(2)箭头函数可以让setTimeout里面的this,绑定定义时所在的作用域,而不是指向运行时所在的作用域

  1. function Timer() {
  2. this.s1 = 0;
  3. this.s2 = 0;
  4. console.log(this)
  5. // 箭头函数
  6. setInterval(() => this.s1++, 1000); //箭头函数没有this,它的this来自绑定时所在的作用域 即外部代码块的this
  7. // 普通函数
  8. setInterval(function () {
  9. this.s2++; //this为window
  10. }, 1000);
  11. }
  12. var timer = new Timer();
  13. setTimeout(() => console.log('s1: ', timer.s1), 3100)
  14. setTimeout(() => console.log('s2: ', timer.s2), 3100)
  1. (3). 箭头函数this不可修改
  1. var obj = {
  2. b : 999
  3. }
  4. var b='666'
  5. function foo2(){
  6. console.log(this)
  7. return ()=>{
  8. console.log(this.b)
  9. }
  10. }
  11. var baz=foo2()
  12. baz();
  13. baz.call(obj)

四、this指向与继承

  1. //示例
  2. function Parent (name,sex){
  3. this.name = name;
  4. this.sex = sex;
  5. }
  6. //添加原型方法
  7. Parent.prototype.show = function(){
  8. console.log("姓名:" + this.name + "性别" + this.sex)
  9. }
  10. //声明函数继承 Parent的函数 并添加自己的函数
  11. function Worker(name,sex,job){
  12. //通过call方法改变Parent的this指向
  13. console.log(this)
  14. Parent.call(this,name,sex)
  15. this.job = job;
  16. }
  17. //此时wk里既有Parent的函数属性 又有了Worker函数的属性
  18. Worker.prototype=Parent.prototype
  19. var wk = new Worker("小明","男","程序员")
  20. console.log(wk.name);
  21. console.log(wk.sex);
  22. console.log(wk.job);
  23. wk.show()