一、函数的定义方式
-
声明式函数定义: function 函数名 (){};这种定义方式,会将函数声明提升到该函数所在作用域的最开头,也是就无论你在这个函数的最小作用域的那儿使用这种方式声明的函数,在这个作用域内,你都可以调用这个函数为你所用。
-
函数表达式:let fun = function(){}; 此方式定义的函数,只能在该作用域中,这段赋值代码执行之后才能通过fun()调用函数,否则,由于变量声明提升,fun === undefined。
-
new Function 形式: var fun1 = new Function (arg1 , arg2 ,arg3 ,…, argN , body );Function构造函数所有的参数都是字符串类型。除了最后一个参数, 其余的参数都作为生成函数的参数即形参。这里可以没有参数。最后一个参数, 表示的是要创建函数的函数体。
总结:
1. 第一种和第二种函数的定义的方式其实是第三种new Function 的语法糖,当我们定义函数时候都会通过 new Function 来创建一个函数,只是前两种为我们进行了封装,我们看不见了而已,js 中任意函数都是Function 的实例。
2. ECMAScript 定义的 函数实际上是功能完整的对象。
二、构造函数
定义:通过 new 函数名 来实例化对象的函数叫构造函数。任何的函数都可以作为构造函数存在。之所以有构造函数与普通函数之分,主要从功能上进行区别的,构造函数的主要功能为初始化对象,特点是和new 一起使用。new就是在创建对象,从无到有,构造函数就是在为初始化的对象添加属性和方法。构造函数定义时首字母大写(规范)。
对new理解:new 申请内存, 创建对象,当调用new时,后台会隐式执行new Object()创建对象。所以,通过new创建的字符串、数字是引用类型,而是非值类型。
函数属性
function User(name) {
var name = name; //私有属性
this.name = name; //公有属性
function getName() { //私有方法
return name;
}
}
User.prototype.getName = function() { //公有方法
return this.name;
}
User.name = 'Wscats'; //静态属性
User.getName = function() { //静态方法
return this.name;
}
var Wscat = new User('Wscats'); //实例化
注意下面这几点:
- 调用公有方法,公有属性,我们必需先实例化对象,也就是用new操作符实化对象,就可构造函数实例化对象的方法和属性,并且公有方法是不能调用私有方法和静态方法的
- 静态方法和静态属性就是我们无需实例化就可以调用
- 对象的私有方法和属性,外部是不可以访问的
三、ES6 中 class 与构造函数的关系
class 为 构造函数的语法糖,即 class 的本质是 构造函数。class的继承 extends 本质 为构造函数的原型链的继承。
类的写法
class Person{ //定义一个名字为Person的类
constructor(name,age){ //constructor是一个构造方法,用来接收参数
this.name = name; //this代表实例对象
this.age = age;
}
say() { //这是一个类的方法,注意千万不要加上function
console.log(this.name + this.age);
}
}
var obj = new Person('aaa',18);
obj.say(); // aaa18
声明构造函数的写法
function Person(name,age){ //构造函数和实例化构造名相同且大写(非强制,但这么写有助于区分构造函数和普通函数)
if(!(this instanceof Person)){ //避免使用者不小心讲Person当作普通函数执行
throw new Error(''请使用 new Person"); //仿ES6 class 中的写法
}
this.name = name;
this.age = age;
}
// 构造函数中的this表示新创建的对象,构造函数自动返回this
Person.prototype.say = function(){
console.log(this.name + this.age);
}
// 构造函数的原型对象,能够被所有实例继承
var obj = new Person('aaa',18); //通过构造函数创建对象,必须使用new运算符
obj.say(); // aaa18
console.log(obj.constructor) // [Function: Person]
console.log(obj instanceof Person); // true
总结:通过class定义的类 和通过构造函数定义的类 二者本质相同。并且在js执行时,会将第一种转会为第二种执行。所以 ES6 class的写法实质就是构造函数。