image.png

this绑定方式

1.默认绑定:window;独立调用也指向window, test()
2.隐式绑定:对象调用 obj.foo() :谁调用就指向谁;(隐式丢失)
3.显式绑定:显示绑定调用 ,apply,bind obj.call(obj),that保存
4.new绑定规则;new foo();
5.箭头函数绑定()=> 父作用域

调用方式

独立调用、自调用、函数调用
对象调用
显示绑定调用:call调用

总结

this是个对象,指向对象,只在运行时产生,不运行不产生
this是为了把方法、属性挂载到对象上

image.png

  1. function foo(){
  2. console.log(this.a)
  3. }
  4. var obj1={
  5. a:2,
  6. foo:foo
  7. }
  8. var obj2 = {
  9. a:3,
  10. foo:foo
  11. }
  12. obj1.foo();
  13. obj2.foo();
  14. obj1.foo.call(obj2);
  15. obj2.foo.call(obj1);

image.png
显示绑定优先级大于隐式绑定

new绑定

image.png

  1. function foo(b){
  2. this.a=b;
  3. }
  4. var obj1={ };
  5. var bar=foo.bind(obj1);
  6. bar(2)
  7. console.log(obj1.a)//2
  8. var baz=new bar(3);
  9. console.log(obj1.a)//?2
  10. console.log(baz.a)//?3

new优先等级大于bind,new bar也隐式有一个绑定,大于bind绑定,从obj1到了baz
bar和foo不是同一个函数,this指向不一样

箭头函数

image.png

that保存

  1. var a=0;
  2. function foo(){
  3. var that=this;
  4. console.log(this);
  5. function test(){
  6. console.log(that);
  7. }
  8. test();//obj that保存了this,虽然是独立调用,但这里是显式改变了this的指向
  9. }
  10. var obj = {
  11. a:1,
  12. foo:foo
  13. }
  14. obj.foo();

image.png
image.png

效果相当于test.call(this)

  1. var a = 0;
  2. function foo() {
  3. // var that = this;
  4. console.log(this);
  5. function test() {
  6. console.log(this);
  7. }
  8. test.call(this);
  9. }
  10. var obj = {
  11. a: 1,
  12. foo: foo
  13. }
  14. obj.foo();

image.png

箭头函数()=>

箭头函数没有、不存在this,没有this指向,向父作用域寻找,用父作用域的this指向
箭头函数内部没有this指向,箭头函数是this指向是由外层函数的作用域来决定的
image.png

  1. var a = 0;
  2. function foo() {
  3. console.log(this)
  4. // var that = this;
  5. // console.log(this);
  6. // function test() {
  7. // console.log(this);
  8. // }
  9. var test=()=>{
  10. console.log(this);
  11. }
  12. test();
  13. }
  14. var obj = {
  15. a: 1,
  16. foo: foo
  17. }
  18. obj.foo();//obj调用foo,foo的this是obj,箭头函数是由外层函数作用域链决定的

image.png

  1. var test=()=>{
  2. console.log(this);
  3. }
  4. var test2=function() {
  5. console.log(this)
  6. }
  7. var obj={
  8. test:test,
  9. test2:test2,
  10. t:function() {
  11. console.log('4')
  12. },
  13. test3:function() {
  14. console.log(this)//obj
  15. this.test();//window
  16. this.test2();//obj
  17. // test()//window
  18. // test2()//window
  19. },
  20. test4:function() {
  21. console.log(this)//obj
  22. var a=()=>{
  23. console.log(this)
  24. }
  25. a()//obj
  26. this.test()//window
  27. return this.test; //window
  28. // return test;//window 与this.test的结果一样
  29. }
  30. }
  31. obj.test3()
  32. obj.test4()();

箭头函数只与箭头函数声明时的作用域有关,与运行时的无关?

  1. var test = () => {
  2. console.log(this);
  3. }
  4. var test2 = function () {
  5. console.log(this)
  6. }
  7. var obj = {
  8. test: test,
  9. test2: test2,
  10. t: function () {
  11. console.log('4')
  12. },
  13. test3: function () {
  14. console.log(this)//obj
  15. var a=()=>{
  16. console.log(this)
  17. }
  18. a()//obj
  19. this.test()//window
  20. return this.test; //window
  21. }
  22. }
  23. obj.test3()();

显示、默认绑定无效

image.png

  1. var a = 0;
  2. function foo() {
  3. // var that = this;
  4. console.log(this);
  5. // function test() {
  6. // console.log(this);
  7. // }
  8. var test = () => {
  9. console.log(this);
  10. }
  11. return test;
  12. }
  13. var obj1 = {
  14. a: 1,
  15. foo: foo
  16. }
  17. var obj2 = {
  18. a:2,
  19. foo:foo
  20. }
  21. obj1.foo()();//默认绑定规则(独立调用对箭头函数)无效;
  22. var bar=foo().call(obj2);//显式绑定规则 无效; 如果call生效,变成window与obj2,但call没有生效,箭头函数永远与父作用域有关,与别的无关
  23. foo.call(obj2)();//foo的this变成了obj2,所有test的this随之改变,箭头函数没有this,向父作用域上找this

image.png

隐式绑定无效

image.png

  1. var obj1={
  2. a:1,
  3. foo:()=>{
  4. console.log(this);
  5. }
  6. }
  7. obj1.foo()//隐式绑定规则无效

只有函数有AO,对象object不能运行,没有AO,对象没有作用域,作用域链向上找是GO,this就是window
this,箭头函数AO里面没有this,箭头函数没有arguments
里面this,外面this完全一样
image.png

new不能实例箭头函数

  1. var foo=()=>{
  2. console.log(this);
  3. }
  4. new foo();

箭头函数不允许当构造函数来使用,因为箭头函数没有this,返回不了this,并且new时也改变不了this,所以箭头函数不能用this
image.png

es6简化写法,两个写法等效,当键名、方法名一致时可以简写
image.png

总结

箭头函数:所有绑定规则全部不适用;
箭头函数的this: 取决于父亲环境中的this 指向;(=>不存在this指向);

obj没有this

  1. var obj1={
  2. a:1,
  3. foo:()=>{
  4. console.log(this);
  5. }
  6. }
  7. obj1.foo()//隐式绑定规则无效

如果对象obj1有this,就打印obj1了,不会打印window
只有函数有AO,对象object不能运行,没有AO,对象没有作用域,作用域链向上找是GO,this就是window
image.png

  1. var obj1={
  2. //obj1.a:1,
  3. a:1,
  4. foo:function(){
  5. console.log(this.a);
  6. }
  7. }
  8. obj1.foo()//1

foo函数的this.a,是函数foo的this,不是obj1的this,为什么this.a能调用obj1里的a?
对象字面量相当于

  1. var obj1=new Object();
  2. obj1.a=1;
  3. obj1.foo=function() {
  4. console.log(this.a);//1
  5. console.log(obj1.a);//1
  6. }
  7. obj1.foo()//因为函数调用使得foo函数的this指向预编译阶段变成了obj1,再执行
  8. /*预编译:foo的this指向obj1
  9. 执行:函数执行,this.a变成obj1.a*/

而不是

  1. var obj1={
  2. this.a:1,
  3. this.foo:function(){
  4. console.log(this.a);
  5. }
  6. }
  7. obj1.foo()//隐式绑定规则无效

构造函数

  1. function Car(){
  2. }
  3. var car=new Car();
  4. console.log(typeof car)
  5. console.log(typeof {})
  6. console.log(car)//Scopes:Global
  7. console.log({})//Scopes:无属性

image.png

  1. console.log(Car.prototype)

image.png
函数声明就有.scope,存有GO

  1. var test=()=>{
  2. }
  3. console.log(test.prototype)

undefined

综合示例

image.png
image.png

  1. var name = 'window';
  2. var obj1 = {
  3. name: '1',
  4. fn1: function () {
  5. console.log(this.name);
  6. },
  7. fn2: () => console.log(this.name),
  8. fn3: function () {
  9. return function () {
  10. console.log(this.name)
  11. }
  12. },
  13. fn4: function () {
  14. return () => console.log(this.name)
  15. }
  16. }
  17. var obj2 = {
  18. name: '2'
  19. }
  20. obj1.fn1();
  21. obj1.fn1.call(obj2);
  22. obj1.fn2();
  23. obj1.fn2.call(obj2);
  24. obj1.fn3()();
  25. obj1.fn3().call(obj2);
  26. obj1.fn3.call(obj2)();
  27. obj1.fn4()();
  28. obj1.fn4().call(obj2);
  29. obj1.fn4.call(obj2)();
  1. var name='window';
  2. var obj1={
  3. name : '1',
  4. fn1:function(){
  5. console.log(this.name);
  6. },
  7. fn2:()=>console.log(this.name),
  8. fn3:function() {
  9. return function() {
  10. console.log(this.name)
  11. }
  12. },
  13. fn4: function() {
  14. return ()=>console.log(this.name)
  15. }
  16. }
  17. var obj2={
  18. name: '2'
  19. }
  20. obj1.fn1();//1 对象调用,隐式绑定,指向调用对象
  21. obj1.fn1.call(obj2);//2 call调用,显示绑定,预编译中this指向obj2,再执行,this.name相当于obj2.name
  22. obj1.fn2();//window 箭头函数,指向父作用域,父环境GO
  23. obj1.fn2.call(obj2);//window 箭头函数所以调用规则全部无效,与父环境一样
  24. obj1.fn3()();//window 返回函数再运行,相当于var a=function() { console.log(this.name) }函数,再运行a(),独立调用,指向window
  25. obj1.fn3().call(obj2);//2 的this指向obj2,相当于obj2.name=2,再打印obj2.name为2
  26. obj1.fn3.call(obj2)();//window 函数fn3的this指向obj2,再执行返回内部函数,但return的函数是新的函数,有新的作用域,返回函数再运行,独立调用,默认绑定,指向window
  27. obj1.fn4()();//1 返回箭头函数再运行,箭头函数的父作用域,父环境,父函数是fn4,fn4是通过函数调用,this指向obj1,箭头函数改变不了this值指向,只能通过父函数this指向来改变
  28. /*1 obj1.fn4() fn4预编译this变成obj1,函数执行,执行结果返回箭头函数,箭头函数再执行,箭头函数的this就是父函数fn4的this
  29. 如果不返回箭头函数,就是函数调用,与obj1.fn3()()结果一样*/
  30. obj1.fn4().call(obj2);//1 返回箭头函数再运行,call不改变箭头函数的this,与上面意思一样
  31. obj1.fn4.call(obj2)();//2 fn4函数的this指向obj2,再运行,返回箭头函数,再运行箭头函数,fn4的this指向obj2,所以内部箭头函数的this也是2

obj1.fn3()(); 返回函数再运行,相当于var a=function() { console.log(this.name) }函数,再运行a(),独立调用,指向window
obj1.fn3().call(obj2)的this指向obj2,相当于obj2.name=2,再打印obj2.name为2
obj1.fn3.call(obj2)(),函数fn3的this指向obj2,但return的函数是新的函数,有新的作用域,返回函数再运行,独立调用,默认绑定,指向window

obj1.fn4()(),返回箭头函数再运行,箭头函数的父作用域,父环境,父函数是fn4,fn4是通过函数调用,this指向obj1
obj1.fn4().call(obj2); 返回箭头函数再运行,call不改变箭头函数的this,与上面意思一样

obj1.fn4.call(obj2)(); fn4函数的this指向obj2,再运行,返回箭头函数,再运行箭头函数,fn4的this指向obj2,所以内部箭头函数的this也是2


image.png
image.png
image.png

构造函数题目

image.png
image.png

  1. function Foo(){
  2. getName=function(){alert(1);};
  3. return this;
  4. }
  5. Foo.getName=function() {alert(2);};
  6. Foo.prototype.getName = function() {alert(3);};
  7. var getName=function() {alert(4);};
  8. function getName() {alert(5); }
  9. Foo.getName();//2
  10. getName();//4
  11. Foo().getName();//1
  12. getName();//1
  13. new Foo.getName();//2
  14. new Foo().getName();//3
  15. new new Foo().getName();//3

()优先级最高

  1. function Foo() {
  2. getName = function () {console.log(1); };
  3. return this;
  4. }
  5. Foo.getName = function () { console.log(2) };
  6. Foo.prototype.getName = function () { console.log(3) };
  7. var getName = function () { console.log(4) };
  8. function getName() { console.log(5) }
  9. Foo.getName();//2
  10. getName();//4
  11. Foo().getName();//1
  12. getName();//1
  13. new Foo.getName();//2
  14. new Foo().getName();//3
  15. new new Foo().getName();//3

详解见 4-三目运算、对象克隆、浅拷贝、深拷贝的作业