1. js 中的 this 指向
- 方法中:方法是谁调用的,那么在方法中this就指向谁(.前面是谁, this就是谁)
let obj = {
name: "obj",
fn: function () {
console.log(this);//obj
}
};
obj.fn();
- 全局中:this 始终指向window
function fn() {
console.log(this);//window
}
fn();
- 构造函数:this 指向实例本身
function Fn(name){
this.name = name;
this.age = 18;
console.log("Fn中的this==>",this); //new Fn()
}
Fn.prototype.sayName = function(){
console.log(this.name); //new Fn()
console.log("sayName中的this==>",this)
}
let fn = new Fn("哈哈");
fn.sayName()
console.log(fn);
- call 、apply 、bind:强制改变this指向
call和apply和bind都是改变this指向的方法,语法:‘
call(新的this指向, pram1, pram2 ...)
apply(新的this指向, [pram1, pram2 ...])
bind方法 返回一个改变this指向之后的新的方法,需要手动调用
var name = 'hao';
function fun() {
console.log (this.name);
}
var obj= {
name: 'yang'
};
fun(); // hao
fun.call(obj); //yang
bind、call、apply 区别?如何实现⼀个bind?
1. apply 、 call 、 bind 三者的区别在于:
三者都可以改变函数的 this
对象指向
三者第⼀个参数都是 this
要指向的对象,如果如果没有这个参数或参数为
undefined
或
null
, 则默认指向全局 window
三者都可以传参,但是 apply
是数组,⽽
call
是参数列表,且
apply
和
call
是⼀次性传⼊参
数,⽽
bind
可以分为多次传⼊
bind 是返回绑定
this
之后的函数,
apply
、
call
则是⽴即执⾏
2.实现 bind 的步骤,我们可以分解成为三部分:
修改 this
指向
动态传递参数
兼容 new
关键字
2.箭头函数中的this指向
- 箭头函数的this指向来自父级上下文, 箭头函数没有自己的this
- 箭头函数的this不会在调用的时候被改变, 在箭头函数声明的时候他的this就已经被永久的确定
let obj = {
name: "obj",
fn: function () {
console.log(this);//obj
let fn2 = ()=>{//闭包
console.log("箭头函数 fn2 中的this指向=========>",this);//obj
}
fn2()
}
};
obj.fn();
3.箭头函数与普通函数的区别
- 箭头函数是匿名函数 箭头函数不能作为构造函数使用 不能使用new
function Fn(name){
this.name = name;
this.age = 18;
console.log("Fn中的this==>",this); //new Fn()
}
let fn = new Fn("哈哈");
let Fn = ()=>{
this.name = name;
this.age = 18;
}
let fn = new Fn(); //Fn is not a constructor
- 箭头函数的this,始终指向父级上下文
let obj = {
a: 100,
fn: function(){
console.log(this);//obj
},
fn2: ()=>{
console.log("fn2====>",this);//window
}
};
obj.fn();
obj.fn2();
- 箭头函数不能通过call apply bind改变this指向,但是可以通过这些方法传递参数
let obj = {
name: "obj",
birth: 1990,
year: 2021,
age: (arg1, arg2)=>{
console.log(this);//window
console.log(arg1, arg2);//obj2
console.log("my age =", this.year - this.birth)
}
}
let obj2 = {
name: "obj2",
birth: 2000,
year: 2020,
};
obj.age.call(obj2,"参数1","参数2")
- 箭头函数没有原型属性
let fn = ()=>{};
console.log(fn);
- 箭头函数没有arguments属性,可以用...展开运算符来接受所有的参数集合
let fn = (...args)=>{ //使用展开运算符接受参数集合
// console.log(arguments);// arguments is not defined
console.log(args); //是一个数组
}
fn(1,2,3)
4.普通函数的arguments和类数组转换成数组
Array.prototype.slice = function (){
console.log(this); //this = arguments
let newArr = [];
for (let i=0;i<this.length;i++){
newArr.push(this[i])
}
return newArr
}
let arr = [1,2,34];
let arr2 = arr.slice();
arr2[0] = 1000;
console.log(arr,arr2);
function fn(){
let arr = Array.from(arguments);
let arr2 = Array.prototype.slice.call(arguments)
let arr3 = [].slice.call(arguments)
console.log(arguments);
console.log(arr,arr2);
}
fn(1,2,3,4,5)