普通对象与函数对象
var o1 = {};
var o2 =new Object();
var o3 = new f1();
function f1(){};
var f2 = function(){};
var f3 = new Function('str','console.log(str)');
console.log(typeof Object); //function
console.log(typeof Function); //function
console.log(typeof f1); //function
console.log(typeof f2); //function
console.log(typeof f3); //function
console.log(typeof o1); //object
console.log(typeof o2); //object
console.log(typeof o3); //object
上面的例子中: o1、o2、o3都是普通对象object,而f1、f2、f3是函数对象function
凡是通过 new Function() 创建的对象都是函数对象,其他的都是普通对象。f1、f2归根结底都是通过 new Function()的方式进行创建的。Function Object 也都是通过 New Function()创建的。
构造函数
function Student(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.intr = function() { console.log(this.name+"年龄是"+this.age) }
}
var lilei = new Student('lilei', 28, 'Software Engineer');
var hmm = new Student('hmm', 23, 'Doctor');
这个例子中lilei、hmm都是构造函数Student的实例
原型对象
JavaScript中,每定义一个对象,对象中都会包含一些预定义的属性,每个普通对象和函数对象都包含__proto__
,而每个函数对象都会有prototype
属性,指向函数的原型对象;
看一个简单示意图:

例子中,
Student
是构造函数(昵称"妈"),其prototype
(原型对象)就是Student.prototype
(昵称"爹"),原型对象(爹)的构造函数属性(妈)是构造函数,而lilei和hmm都是构造函数Student(妈)的实例(儿子/女儿),儿子/女儿都继承(__proto__
)了爹,遗传了爹的方法和属性,用公式表示即:
Student===Student.prototype.constructor; //true
lilei.__proto__===Student.prototype; //true
- 构造函数具有
prototype
属性,指向原型对象 - 原型对象具有
constructor
属性,指向构造函数 - 实例对象具有
__protot__
属性,指向原型对象
从 ECMAScript 6 开始,
[[Prototype]]
可以通过Object.getPrototypeOf()
和Object.setPrototypeOf()
访问器来访问。这个等同于 JavaScript 的非标准但许多浏览器实现的属性__proto__
。
原型对象其实就是普通对象,但Function.prototype除外,它是函数对象,且没有prototype属性(前面说函数对象具有prototype属性)
function Student(){};
console.log(Student.prototype) //Student{} 空对象,具有constructor属性
console.log(typeof Student.prototype) //object
console.log(typeof Function.prototype) // function,这个特殊
console.log(typeof Object.prototype) // object
console.log(typeof Function.prototype.prototype) //undefined
原型对象的应用
原型对象的应用主要就是继承
var Student = function(name){
this.name = name; // tip: 当函数执行时这个 this 指该构造函数的实例
};
/*给Student添加getName方法*/
Student.prototype.getName = function(){
return this.name; // tip: 当函数执行时这个 this 指该构造函数的实例
}
var lilei = new Student('lilei');
console.log(lilei.name); //'lilei' 此时 lilei 已经有 name 这个属性了
console.log(lilei.getName()); //lilei
原型链

lilei.__proto__ 是Student.prototype
Student.__proto__ 是Function.prototype
Student.prototype.__proto__ 是Object.prototype
Object.__proto__ 是Function.prototype,Object也是构造函数
Object.prototype__proto__ 是null
本文借鉴了Yi罐可乐
: 最详尽的 JS 原型与原型链终极详解,没有「可能是」
网友评论