原型和原型链
原型规则和原型设计模式
原型规则
只要创建一个新函数,就会根据一组特定的规则为该函数创建一个 prototype属性,这个属性指向函数的原型对象。默认情况下,所有原型对象都会自动获得一个 constructor(构造函数)属性,这个属性指向 prototype 属性所在的函数。
- 引用类型(数组、对象、函数)都具有对象属性,都可以自由扩展属性;
var array = [] array.age = 1 array.name= "string"
- 引用类型都有一个_proto_ 属性(隐式原型),属性值是一个普通对象;
- 函数都具有一个prototype(显示原型),属性值也是一个普通原型;
- 引用类型的隐式原型指向其构造函数的显式原型;(obj.proto === Object.prototype);
- 当试图获取一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的**proto**(即它的构造函数的prototype)中去寻找;普通的对象没有prototype,但是有_proto_ 属性(隐式原型)。
原型的作用就是给这个类的每一个对象都添加一个统一的方法,在原型中定义的方法和属性都是被所以实例对象所共享。
eg:var animal = function(id) { this.id = id } //通过prototype添加func; animal.prototype.run = function() { return this.id } // 实例一个dog let dog = new animal(3) dog.run() // 3
原型链
当试图得到一个对象f的某个属性时,如果这个对象本身没有这个属性,那么会去它的_proto_(即它的构造函数的prototype)obj._proto_中去寻找;当obj._proto也没有时,便会在obj._proto.proto(即obj的构造函数的prototype的构造函数的prototype)中寻找;
以上例说明,当试图得到 dog 对象的name属性时,dog对象本身并没有这个属性,那便会从它的_proto_(隐式原型),即它的构造函数 animal 的prototype中寻找,如果animal中也没有,则会继续往animal的构造函数的prototype中继续寻找,直到最后(Null)。
设计模式
-
1.工厂模式
通过函数内部创建对象,赋予属性和方法后再将此对象返回
eg:function Animal() { let cat = new Object() cat.name = 'cat' cat.age = 1 cat.run = function() { return 'cat is running' } return cat } let animal = Animal() animal.name // cat animal.age // 1 animal.run() // cat is running
-
2.构造模式
在1的基础上,但不创建新对象,而使用this关键字替代
eg:function Animal() { this.name = 'dog' this.age = 1 this.run = function() { return 'dog is running' } } let dog = new Animal() dog.name // dog dog.age // 1 dog.run() // dog is running
-
3.原型模式
利用函数的prototype进行定义,实现此函数的实例属性共享
eg:function Animal() { Animal.prototype.name = 'animal-proto' Animal.prototype.run = function(){ return 'Animal run' } } let dog = new Animal() dog.name // dog dog.run() // Animal run
-
4.混合模式
利用构造模式定义属性,原型模式定义方法和共享属性
eg:function Animal() { this.name = 'Animal' } Animal.prototype.run = function() { return this.name + 'is running' } let dog = new Animal() dog.name // Animal dog.run() // Animal is running
-
4.动态模式
根据判断条件来动态初始化原型
eg:function Animal() { this.name = 'Animal' if(typeof Animal.run === "undefined"){ Animal.prototype.run = function() { return this.name + 'is running' } } let dog = new Animal() dog.name // Animal dog.run() // Animal is running
instanceof 和 typeof
-
instanceof 运算符用于测试构造函数的 prototype 属性是否出现在对象原型链中的任何位置,规则简单来说就是 obj的 proto 是不是强等于 object.prototype,不等于再找 obj.proto .proto 直到 proto 为 null.
function instance_of(cat, annimal) { var flag = annimal.prototype; cat = cat.__proto__; while (true) { if (cat === null) return false; if (flag === cat) // 判断 falg 严格等于 cat return true; cat= cat__proto__; // 继续向上寻找 } }
-
typeof
1.typeof 则是判断参数是什么类型的实例,返回值为说明运算数类型的字符串
。
2.返回值结果:“number”、“string”、“boolean”、“object”、“function”、“undefined”
3.若参数为引用类型,始终返回“object”,对于Array、null始终返回“object”,所以用typeof来判断参数类型有很大的局限性。