浏览器 指向window node js 指向global
var a = 10; function foo (){console.log(this.a)}
foo();
在严格模式下,this指向undefined.
"use strict";var a = 10;function foo() {console.log('this1',this);console.log(window.a);console.log(this.a)
};console.log(window.foo);console.log('this2',this);foo();
严格模式的目的:
1.消除JavaScript语法中,不合理,不严谨的地方.
2.消除代码中一些不安全的地方,保证代码的安全运行.
3.提高JavaScript程序的运行效率.
4.为以后新版本的JavaScript做好准备.
在js脚本的开头添加"use strict"开启严格模式单引号同理
严格模式的特征:
1.不允许使用未声明的变量 a = ?
2.不允许删除变量或函数. delate
3.函数中不允许出现同名的参数. function(a,a){}
4.eval语句的作用域是独立的, eval(‘var a = 100’)
5.不允许使用with语句
6.不允许写入只读属性
7.不允许使用八进制数 0o
8.不能在if语句中声明函数
9.禁止使用this表示全局对象
let a = 10;const b = 20;function foo () {console.log(this.a);console.log(this.b)};foo();console.log(window.a)var a = 1;function foo () {var a = 2;console.log(this);console.log(this.a)};foo()var a=1;function foo(){var a=2;function inner(){console.log(this.a)}inner()}foo()
隐式绑定与丢失
隐式丢失其实就是被隐式绑定的函数在特定的情况下会丢失绑定对象
当使用另一个变量来给函数取别名或者将函数作为参数传递时会被隐式赋值,回调函数丢失this绑定
function foo(){console.log(this.a)};var obj={a:1,foo};var a=2;var foo2=obj.foo;obj.foo();foo2();function foo(){console.log(this.a)};var obj={a:1,foo};var a=2;var foo2=obj.foo;var obj2={a:3,foo2:obj.foo};obj.foo();foo2();obj2.foo2();function foo(){console.log(this.a)};function doFoo(fn){console.log(this);fn()};var obj={a:1,foo};var a=2 ;doFoo(obj.foo)
隐式丢失不是链
显示绑定
强行使用某些方法,改变函数内this的指向
通过call()、apply()或者bind()方法直接指定this的绑定对象
使用.call()或者.apply()的函数是会直接执行的
bind()是创建一个新的函数,需要手动调用才会执行
function foo(){console.log(this.a)};var obj={a:1};var a=2;foo();foo.call(obj);foo.apply(obj);foo.bind(obj)
如果call、apply、bind接收到的第一个参数是空或者null、undefined的话,则会忽略这个参数
function foo(){console.log(this.a)};var a=2;foo.call();foo.call(null);foo.call(undefined)var obj1={a:1};var obj2={a:2,foo1:function(){console.log(this.a)},foo2:function(){setTimeout(function(){console.log(this);console.log(this.a)},0)}};var a=3;obj2.foo1();obj2.foo2()var obj1={a:1};var obj2={a:2,foo1:function(){console.log(this.a)},foo2:function(){function inner(){console.log(this);console.log(this.a)}inner()}};var a=3;obj2.foo1();obj2.foo2()function foo(){console.log(this.a)};var obj={a:1};var a=2;foo();foo.call(obj);foo().call(obj)function foo(){console.log(this.a);return function(){console.log(this.a)}};var obj={a:1};var a=2 ;foo();foo.bind(obj);foo().bind(obj)
// 中间被吞了的原因是因为控制台只会返回最后一个
function foo(){console.log(this.a);return function(){console.log(this.a)}};var obj={a:1};var a=2;foo.call(obj)()
//不是按链走结果为 1 2
var obj={a:1,foo:function(b){b=b||this.a;return function(c){console.log(this.a+b+c)}}};var a=2;var obj2={a:3};obj.foo(a).call(obj2,1);obj.foo.call(obj2)(1)
new绑定
function Person(name){this.name=name};var name='window';var person1=new Person('yuanrenxue');console.log(person1.name);Person(name){this.name=name;this.foo1=function(){console.log(this.name)};this.foo2=function(){return function(){console.log(this.name)}}};var person1=new Person('person1');person1.foo1();person1.foo2()();var name='window';function Person(name){this.name=name;this.foo=function(){console.log(this.name);return function(){console.log(this.name)}}};var person2={name:'person2',foo:function(){console.log(this.name);return function(){console.log(this.name)}}};var person1=new Person('person1');person1.foo()();person2.foo()();var name='window';function Person(name){this.name=name;this.foo=function(){console.log(this.name);return function(){console.log(this.name)}}};var person1=new Person('person1');var person2=new Person('person2');person1.foo.call(person2)();person1.foo().call(person2);
箭头函数绑定
箭头函数内的this是由外层作用域决定的,call对其没有影响
使用new来创建对象时发生了什么
创建(或者说构造了)一个新对象
这个新对象进行[[prototype]]连接, 将新对象的原型指向构造函数,这样新对象就可以访问到构造函数原型中的属性
改变构造函数this 的指向为新建的对象,这样新对象就可以访问到构造函数中的属性