普通对象和函数对象
let obj1 = {}
let obj2 = new Object()
let obj3 = new fun3()
let fun1 = function () {}
let fun2 = new Function('str', 'console.log(str)')
function fun3 () {}
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 obj1); //object
console.log(typeof obj2); //object
console.log(typeof obj3); //object
可以看出,上面的obj1, obj2, obj3都是普通对象,fun1,fun2,fun3为函数对象。凡是通过 new Function() 创建的对象都是函数对象,其他的都是普通对象。f2,f3,归根结底都是通过 new Function()的方式进行创建的。Function Object 也都是通过 New Function()创建的。
构造函数
function Animal (name, age) {
this.name = name
this.age = age
this.say = function () {
console.log('我是个' + age + '的' + name)
}
}
var cat = new Animal('cat', 49)
var dog = new Animal('dog', 2)
cat和dog都是Animal的实例,他们都有一个构造函数constractor属性,指向了Animal。即实例的构造函数属性指向构造函数。
console.log(cat.constructor == Animal) // true
console.log(dog.constructor == Animal) // true
原型对象
对于函数对象来说,每创建一个函数对象,都会有一个prototype属性,这个属性就是函数的原型对象。而每个对象,无论是函数对象,还是普通对象都会有一个__proto__属性。
function Aaimal () {}
Animal.prototype.name = 'cat'
let cat = new Animal()
consoel.log(cat.name) // cat
原型对象:就是一个普通的对象:
function Animal () {}
Animal.prototype = {
name: 'cat'
}
其实每一个原型对象,还会有一个默认的属性,就是constructor,这个属性指向原型对象的构造函数。
function Animal () {}
Animal.prototype = {
name: 'cat'
}
console.log(Animal.prototype.constructor == Animal) // true
let cat = new Animal()
console.log(cat.constructor == Animal) // true
所以原型对象(Animal.prototype)是构造函数的实例。而且我们可以看到原型对象都是普通对象,但是Function.prototype除外。他是函数对象,没有prototype。
function Animal(){};
console.log(Animal.prototype) //Animal{}
console.log(typeof Animal.prototype) //Object
console.log(typeof Function.prototype) // Function,这个特殊
console.log(typeof Object.prototype) // Object
console.log(typeof Function.prototype.prototype) //undefined
Function.prototype是函数对象的原因:
var A = new Function ();
Function.prototype = A;
原型对象的作用:原型对象的作用主要是用来实现继承的。
function Animal (name, age) {
this.name = name
this.age = age
}
Animal.prototype.say = function () {
console.log('I am a' + this.age + '岁的' + this.name)
}
let cat = new Animal(1, 'cat')
cat.say() // I am a 1岁的cat
所以,我们可以看到,在构造函数Animal的原型对象上添加say方法,然后cat实例就可以继承到Animal的属性。
__proto__:我们之前说过,无论是普通对象,还是函数对象,都会默认有一个__proto__属性。用于指向创建他的构造函数的原型对象。
function Animal () {}
let cat = new Animal()
console.log(cat.__proto__ == Animal.prototype) //true
这种链接是存在于实例和构造函数的原型对象之间。而不是实例和构造函数之间。
构造器
创建对象的方式:
let obj = {}
let obj = new Object()
相当于是obj是Object的实例。那么也就是说:
obj.__proto__ == obj.constructor
obj.constructor == obj.prototype
创建对象的构造器不仅仅有 Object,也可以是 Array,Date,Function等。所以我们也可以构造函数来创建 Array、 Date、Function.
var b = new Array();
b.constructor === Array;
b.__proto__ === Array.prototype;
var c = new Date();
c.constructor === Date;
c.__proto__ === Date.prototype;
var d = new Function();
d.constructor === Function;
d.__proto__ === Function.prototype;
函数对象
JavaScript内置12个函数对象(其中Json是Es6中新增),Global不能直接访问,Arguments仅在函数调用时由JS引擎创建,Math,JSON是以对象形式存在的,无需new。它们的proto是Object.prototype。
Number.__proto__ === Function.prototype // true
Number.constructor == Function //true
Boolean.__proto__ === Function.prototype // true
Boolean.constructor == Function //true
String.__proto__ === Function.prototype // true
String.constructor == Function //true
// 所有的构造器都来自于Function.prototype,甚至包括根构造器Object及Function自身
Object.__proto__ === Function.prototype // true
Object.constructor == Function // true
// 所有的构造器都来自于Function.prototype,甚至包括根构造器Object及Function自身
Function.__proto__ === Function.prototype // true
Function.constructor == Function //true
Array.__proto__ === Function.prototype // true
Array.constructor == Function //true
RegExp.__proto__ === Function.prototype // true
RegExp.constructor == Function //true
Error.__proto__ === Function.prototype // true
Error.constructor == Function //true
Date.__proto__ === Function.prototype // true
Date.constructor == Function //true
Math.__proto__ === Object.prototype // true
Math.construrctor == Object // true
JSON.__proto__ === Object.prototype // true
JSON.construrctor == Object //true
所有的构造器都来自于 Function.prototype
,甚至包括根构造器Object
及Function
自身。所有构造器都继承了·Function.prototype·的属性及方法。
总结:
对象分为普通对象,和函数对象。每个函数对象都有一个prototype属性,而无论普通对象还是函数对象都有一个__proto__属性。每个实例的__proto__指向构造函数的原型对象:
function Animal () {}
let cat = new Animal()
console.log(cat.__proto__ == Animal.prototype)
构造函数的原型对象的构造函数指向构造函数的原型:
function Animal () {}
Animal.prototype.constructor = Animal.prototype
实例的原型对象指向构造函数的原型对象:
function Animal () {}
let cat = new Animal()
Animal.prototype = Animal.prototype