作用域
函数提升:函数的调用可以在函数定义之前,因为存在函数提升,函数整体定义提升
变量提升:变量提升的只是定义,赋值还在原地
console.log(a);
var a = 11;
等同于
var a;
console.log(a);
a = 11;
this
this是在函数执行时,动态获取上下文决定的,不是创建时决定的。 this代表谁调用这个函数
1.普通函数执行,this指向全局,window
2.隐式绑定,作为对象的方法调用,指向这个对象
const o1 = {
text: 'o1',
fn: function() {
return this.text
}
}
o1.fn(); // this指向o1
const o2 = {
text: 'o2',
fn: function() {
return o1.fn()
}
}
o2.fn(); //函数中的this依然指向o1,因为函数的最终执行是o1.fn()
要想让this指向o2, 可以用bind, call, this
o2.fn.call(o2)
const o3 = {
text: 'o3',
fn: function() {
let fn = o1.fn //只赋值了函数的引用,没有调用函数
return fn()
}
}
o3.fn(); //this指向o3
3.显示绑定 call, apply, bind
函数想要改变this的指向,可以函数调用call,apply,bind方法 call, apply是直接执行函数,返回结果; bind返回的是新函数,需要再手动执行
call:fn.call(context, arg1, arg2,...)
context为想要指向的this值,arg1,arg2...为函数本身需要的参数
const fun = function(a, b){
...
};
fun.call(o1, a, b);
apply:fn.apply(context, [arg1, arg2]); apply和call类似,只是参数传递格式不同
使用
1.获取数组最值
const num = [1,2,3,4,5];
Math.max.call(Math, ...num);
//num没有max方法,借用Math.max
2.验证是否是数组
Object.prototype.toString.call(num) // '[object Array]'
//toString是object类方法
bind, fn.bind(context, arg1, arg2, ...)
手写bind
Function.protoType.myBind = function(){
const _this = this; //指向当前调用bind的函数;
if(typeof _this !== 'function'){
提示“应该是函数调用bind方法”
}
const args = Array.prototype.slice.call(arguments);
//arguments是传入该函数的参数,类数组对象,函数内部语法可以自动获取
//这里转成数组,第一项是要指向的this,其他数组元素为函数的其他参数
const newThis = args.shift();
return function(){
return _this.call(newThis,...args)
}
}
手写call
Function.prototype.myCall = function(){
const _this = this; //同上
if(typeof _this !== 'function'){
提示“应该是函数调用bind方法”
}
const args = Array.prototype.slice.call(arguments);
const newThis = args.shift();
//将这个函数,作为属性给要指向的this对象,
//作为属性方法调用,再删除属性
const fn = Symbol('call'); //确保属性不重名
newThis[fn] = _this;
const result = newThis[fn](...args);
delete newThis[fn];
return result;
}
4.作为构造函数使用
this指向新创建的对象
function Name(name){
this.name = name;
}
const a = new Name('aaa');
new原理
1.new的作用
执行构造函数,返回一个实例对象;实例对象可以访问构造函数原型链上的属性
new执行总是返回一个对象,要么是实例对象,要么是return语句返回的对象
function Person(){
this.name='aaa';
return '111';
}
new Person(); // { name: 'aaa'}
function Per(){
this.name = 'aaa';
return {age: 11;}
}
new Per(); // {age: 11}
2.new的原理
创建一个新对象; 将构造函数的作用域赋给新对象(this指向新对象); 执行构造函数中的代码(给这个对象添加属性/方法); 返回这个新对象
function create(fn, ...args){
let obj = {};
Object.setPrototypeOf(obj, fn.prototype);
let result = fn.call(obj,...args);
return result instanceOf Object ? result : obj;
}