Js面向对象进阶

2019-03-01  本文已影响0人  Speng

一.普通对象与函数对象

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创建的对象。

上一篇 下一篇

猜你喜欢

热点阅读