理解函数调用

函数调用方式

1、作为函数被调用 fun()

2、作为一个对象的方法被调用 obj1.fun()

3、作为一个构造函数被调用 new fun()

4、 通过函数的apply和call方法调用 fun.call(); fun.apply()

函数声明和函数表达式的区别

函数声明

function fun1(){
    console.log(this);
}

函数表达式

//匿名函数
var fun1 = function(){
    console.log(this);
}
//具名函数
var fun1 = function fun2(){
    console.log(this);
}

区别:

1、利用函数声明来定义的函数会被变量提升,而利用函数表达式定义的函数则会被认为是普通的变量赋值表达式,不会被变量提升。

2、利用函数声明来定义时,必须要给函数命名,而利用函数表达式定义的函数可以不用对函数进行命名

3、在最外层使用函数声明来定义函数时,该函数可被作为全局变量被调用;而利用函数表达式定义的函数则会被当做该变量的局部变量,不能作为全局变量被调用。

示例

consloe.log(bar); //bar(){}
consloe.log(foo); //undefined
function bar(){
    console.log(this);
}
var foo = function(){
    console.log(this);
}
var fun1 = function fun2(){
    console.log(this);
}
bar(); //Window
foo(); //Window
fun2(); //undefined

作为构造函数调用

使用关键字new调用函数会触发以下几个动作:

1、创建一个空的对象。

2、该空对象作为this参数传递给构造函数。

3、新构造的对象作为new运算符的返回值

//定义构造函数Person
function Person(){
    return this;
}
var person1 = new Person();//利用new调用构造函数来创建person1对象

// var person1 = new Person()过程
var temp = {};//临时创建一个空的对象
var temp = Person.call(temp); //该空对象作为this参数传递给构造函数,创建一个新的构造对象
var person1 = temp;//新构造的对象作为new运算符的返回值

总结

1、如果构造函数返回的是一个对象时,该对象将作为整个表达式的值返回,而传入构造函数的this将被舍弃。

2、如果构造函数返回的是一个非对象类型的值时,该对象将被忽略,返回新构建的对象。

var school = {
    name: 'sise',
    id: 1264
}
//定义构造函数Stu
function Stu(name){
    this.name = name;
    return school;//返回一个对象
}
//定义构造函数Person
function Person(name){
    this.name = name;
    return 123;//返回一个非对象类型的值
}
var stu1 = new Stu("张三");
var person1 = new Person("张三");
consloe.log(stu1);// {name: "sise", id: 1264}
consloe.log(person1);// Person {name: "张三"}

箭头函数与普通函数 this 指向的区别

箭头函数的this指向是固定的,绑定在其声明的位置;而普通函数的this指向是可变的,指向其调用位置的上下文。

var name = "window";
var obj1 = {
name: 'obj',
    arrow: () => {
        console.log("arrow:" + this.name ,this);
        },
    func: function(){
            console.log("function:" + this.name ,this);
        }
}
var obj2 = {
    name: 'obj2'
}
    obj1.arrow.call(obj2); //将arrow的this指向obj2 结果:arrow: window Window{}
    obj1.func.call(obj2);//将func的this指向obj2 结果: func: obj2 obj2{}