构造函数的概念
- 任何函数都可以当成构造函数
function CreateFunc(){ }
- 只要把一个函数通过new的方式来进行调用,我们就把这一次函数的调用方式称之为:构造函数的调用
-
new CreateFunc(); 此时CreateFunc就是一个构造函数
-
CreateFunc(); 此时的CreateFunc并不是构造函数
构造函数的执行过程
var p1=new Person();
- 1、创建一个对象 (我们把这个对象称之为Person构造函数的实例)-
_p1
- 2、创建一个内部对象,
this
,将this指向该实例(_p1) - 3、执行函数内部的代码,其中,操作this的部分就是操作了该实例(_p1)
- 4、返回值:
- a、如果函数没有返回值(没有return语句),那么就会返回构造函数的实例(p1)
- b、如果函数返回了一个基本数据类型的值,那么本次构造函数的返回值是该实例(_p1)
- c、如果函数返回了一个复杂数据类型的值,那么本次函数的返回值就是该值
闭包
变量作用域
- 变量作用域的概念:就是一个变量可以使用的范围
- JS中首先有一个最外层的作用域:称之为全局作用域
- JS中还可以通过函数创建出一个独立的作用域,其中函数可以嵌套,所以作用域也可以嵌套
作用域链
- 由于作用域是相对于变量而言的,而如果存在多级作用域,这个变量又来自于哪里?这个问题就需要好好地探究一下了,我们把这个变量的查找过程称之为变量的作用域链
- 作用域链的意义:查找变量(确定变量来自于哪里,变量是否可以访问)
- 简单来说,作用域链可以用以下几句话来概括:(或者说:确定一个变量来自于哪个作用域)
- 查看当前作用域,如果当前作用域声明了这个变量,就确定结果
- 查找当前作用域的上级作用域,也就是当前函数的上级函数,看看上级函数中有没有声明
- 再查找上级函数的上级函数,直到全局作用域为止
- 如果全局作用域中也没有,我们就认为这个变量未声明(xxx is not defined)
- 再查找上级函数的上级函数,直到全局作用域为止
- 查找当前作用域的上级作用域,也就是当前函数的上级函数,看看上级函数中有没有声明
- 查看当前作用域,如果当前作用域声明了这个变量,就确定结果
闭包问题的产生原因
- 函数执行完毕后,作用域中保留了最新的a变量的值
闭包的应用场景
- 模块化
- 防止变量被破坏
函数的4种调用方式
- 在
ES6之前
,函数内部的this是由该函数的调用方式决定的- 函数内部的this跟大小写、书写位置无关
- 1、函数调用
-
var age=18; var p={ age:15 say:function(){ console.log(this.age);//window.age:18 } } var s1=p.say s1(); //函数调用
+ 2、方法调用
+ ```js
var age=18;
var p={
age:15
say:function(){
console.log(this.age);//this:p
//this.age->p.age:15
}
}
p.say()//方法调用
- 3、new调用(构造函数)
var age=18;
var p={
age:15
say:function(){
//this:say构造函数的实例,实例中并没有age属性,值为:undefined
console.log(this.age);
}
}
new p.say()//构造函数调用
//相当于:
var s1=p.say;
new s1();
- 4、上下文方式(call、apply、bind)
var length=21;
function f1(){
console.log(this.length);
}
f1.call([1,3,5]) //3
f1.apply(this) //window.length:21
f1.call(5) //undefined
- 上下文模式应用场景:
- 一些需要指定this的情况,比如$.each方法回调函数内部的this
- 判断数据类型:
- Object.prototype.toString.call(1);
- 在ES6的箭头函数之前的时代,想要判断一个函数内部的this指向谁,就是根据上面的四种方式来决定的