一.普通对象与函数对象
js中万物皆对象!但对象也是有区别的。分为普通对象和函数对象,Object 、Function 是 JS 自带的函数对象。下面举例说明
var o1 = {};
var o2 = new Object();
var o3 = new f1();
function f1(){};
var f2 = function(){};
var f3 = new Function('fn','console.log(fn)');
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 为普通对象,f1 f2 f3 为函数对象。
怎么区分,其实很简单,凡是通过 new Function() 创建的对象都是函数对象,其他的都是普通对象。
Function Object 最后是通过 New Function()创建的。
二.构造函数
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function() { alert(this.name) }
}
var person1 = new Person('张三', 18, '搬砖');
var person2 = new Person('李四', 18, '和泥');
上面的例子中 person1 和 person2 都是 Person 的实例。
这两个实例都有一个 constructor (构造函数)属性,该属性(是一个指针)指向 Person。
console.log(person1.constructor == Person); //true
console.log(person2.constructor == Person); //true
记住两个概念(构造函数、实例):
person1 和 person2 都是 构造函数 Person 的实例
公式:
实例的构造函数属性(constructor)指向构造函数
三. 原型对象
在 JavaScript 中,每当定义一个对象(函数也是对象)时候,对象中都会包含一些预定义的属性。其中每个函数对象都有一个prototype 属性,这个属性指向函数的原型对象。
function Person() {}
Person.prototype.name = '张三';
Person.prototype.age = 18;
Person.prototype.job = '搬砖';
Person.prototype.sayName = function() {
alert(this.name);
}
var person1 = new Person();
person1.sayName(); // '张三'
var person2 = new Person();
person2.sayName(); // '张三'
console.log(person1.sayName == person2.sayName); //true

上图中可以知道,实例
__protpo__
指向的是原型对象。实例的构造函数的prototype也是指向的原型对象。
原型对象的construor指向的是构造函数。
牢记!以下四条:
1.每个对象都具有一个名为
__proto__
的属性;
2.每个构造函数都具有一个名为prototype的方法;
3.每个对象的__proto__
属性指向自身构造函数的prototype;
4.每个对象都有__proto__
属性,但只有函数对象才有 prototype 属性
四、原型链
简单理解就是原型组成的链,对象的__proto__
它的是原型,而原型也是一个对象,也有__proto__
属性,原型的__proto__
又是原型的原型,就这样可以一直通过__proto__
想上找,这就是原型链,当向上找找到Object的原型的时候,这条原型链就算到头了。
原型对象和实例之间有什么作用
通过一个构造函数创建出来的多个实例,如果都要添加一个方法,给每个实例去添加并不是一个明智的选择。这时就该用上原型了。
在实例的原型上添加一个方法,这个原型的所有实例便都有了这个方法。
var Met = function (name) { this.name = name; }
var met = new Met('met')
var met1 = new Met()
met.__proto__.say=furnction(){
console.log('hello world')
}
met.say()
met1.say()
按照JS引擎的分析方式,在访问一个实例的属性的时候,现在实例本身中找,如果没找到就去它的原型中找,还没找到就再往上找,直到找到。这就是原型链。
Met.__proto__===Function.prototype //true
只有函数有prototype,对象是没有的
但是函数也是有__proto__
的,因为函数也是对象。函数的__proto__
指向的是Function.prototype。也就是说普通函数是Function这个构造函数的一个实例。
instanceof原理

instanceof是判断实例对象的
__proto__
和生成该实例的构造函数的prototype是不是引用的同一个地址。注意:实例的instanceof在比较的时候,与原型链上向上找的的构造函数相比都是true
met.__proto__===Met.prototype//true
met instanceof Met //true
Met.prototype===Object.prototype//false
Met.prototype.__proto__===Object.prototype//true
met instanceof Object //true
met.__proto__.constructor===Met//true
met.__proto__.constructor===Object//fasle
new运算符的原理
1.一个新对象被创建。它继承自foo.prototype。
2.构造函数返回一个对象。在执行的时候,相应的传参会被传入,同时上下文(this)会被指定为这个新的实例。
3.new foo等同于new foo(), 只能用在不传递任何参数的情况
4.如果构造函数反悔了一个对象,那个这个对象会取代整个new出来的结果。如果构造函数没有返回对象,那个new出来的结果为步骤1创建的对象。
网友评论