On Javascript in prototype, the prototype chain, inheritance

Relationship constructor prototype, examples of three

Constructor:

A constructor is a common way to create objects, other ways to create objects also include factory pattern, prototype model, object literal when we look at a simple constructor:


function Product (name, role){ //构造函数的命名约定第一个字母使用大写的形式!
    this.name = name;
    this.role = role;
}

(1) Each constructor has a prototypeproperty, we can Chormeprint out the console Product.prototypeproperties.

(2) printed results can be found via the console, Product.prototypeproperty is actually a pointer to an object that has a constructorproperty. ( __proto__Attribute property is non-standard browser introduced, enabling developers to easily debug, you can not bother!)

(3) Therefore, the constructor prototypeproperty points to an object that is what we will say next prototype

prototype

"Javascript advanced programming" is described the prototype of this concept:

At any time, simply create a new function is created based on a specific set of rules for the function a prototypeproperty that points to the prototype object function. By default, all objects will automatically get a prototype constructor()constructor property, this attribute contains a pointer to prototypeattribute a function pointer is located.

I believe you are ignorant forced to read this sentence, Let me explain this sentence:

(1) The constructor of the prototypeattribute points to the object will be called the prototype
(2), the prototype of this object, a constructorproperty and refers back to its own constructor.
Understand (3) Figure II below, may be more clearly the relationship between the two.

Examples

Constructor creates an object through a process we call instantiation , created out of objects called instances . Now we are through our Productcreating an instance (object) constructor.

function Product (name, role){
    this.name = name;
    this.role = role;
}

var p1 = new Product('apple', 'fruit');

(1) Now let's add a method to prototype

Product.prototype.greet = function(){
    console.log('我是一个很甜的'+ this.name +', 买我!')
}

(2) call the method in Example

p1.greet();  //我是一个很甜的apple, 买我!

You can see, the way we add in the prototype, but examples can be used so that we can draw the following conclusions:

Examples of the prototype all properties and methods which will be connected to its corresponding constructor!

(3) configured / example / prototype triangle

It may be the relationship between the three better understood from the configuration / following examples / Prototype triangle:

in conclusion

  • Constructor perspective standing : .prototype function name attribute is the prototype object constructor
  • Examples of objects standing in perspective : the function name .prototype This object is object prototype object instance
  • Prototype Formula Inheritance : prototype object properties and methods can be directly accessed instance object.

Prototype chain

Understanding the prototype chain

From the conclusion of the first part, we know, instance of an object can directly access the properties and methods of the prototype object. In fact, the prototype nature object is an object, it is actually a new Object () to instantiate out. The prototype object can also access Object.prototype of all properties and methods. in fact, this constitutes a prototype chain this important concept.

Code Analysis

Let's analyze the following piece of code


//创建Product构造函数
function Product (){
    this.name = 'apple';
}
//给Product构造函数的原型增加方法
Product.prototype.greet = function(){
    console.log('我是一个很甜的'+ this.name +', 买我!');
}

//创建SalesProduct构造函数
function SalesProduct (){
    this.name = 'bad apple';
}

//将Product的实例对象直接赋给SalesProduct的原型
SalesProduct.prototype = new Product();

//给SalesProduct的原型一个方法
SalesProduct.prototype.anotherGreet = function(){
    console.log('我是一个' + this.name + ',不要买我!');
}

//实例化SalesProduct
var p2 = new SalesProduct(); 
p2.greet(); //我是一个很甜的bad apple, 买我!

( 1 ) 在上面的代码中,我们没有使用SalesProduct默认提供的原型,而是将其换了一个新的原型.该新原型Product的实例.
( 2 ) 所以,该新原型不仅作为Product实例拥有其全部属性和方法, 其内部还拥有一个指针,指向Product.prototype.我们可以从调用p2.greet()的结果可以看出.
( 3 ) 所以,可以得出以下的链条p2 => SalesProduct.prototype => Product.prototype => Object.prototype
( 4 ) 上面的这一个链条就形成了原型链.值得注意的是,Product.prototype最后还指向了Object.prototype,这也是所有的自定义对象都会具有toString(),hasOwnProperty()等方法的原因.

重要结论

( 1 ) 原型的顶端: Object.prototype, 任何一个默认的内置的函数的原型都继承自Object.prototype.
( 2 ) 原型链 : Js的对象结构中出现的指向Object.prototype的一系列原型对象,我们称之为原型链.
( 3 ) 属性搜索原则 : 在访问对象的属性和方法时, 会在当前对象中查找, 如果没有找到, 会一直沿着原型链上的原型对象向上查找, 直到找到Object.prototype为止
( 4 ) 写入原则 : 如果给对象设置属性和方法, 都是在当前对象上设置.

实现继承的其他方法

原型链继承是Javascript中实现继承的主要方式,但是原型链的继承存在一个问题,就是当对象有一个引用类型的属性时,该引用类型会被其后的所有实例所共享.下面的代码可以说明这一个问题.

function TypeOne(){
        this.colors = ['red', 'blue', 'green'];
    }

    function TypeTwo(){}

    TypeTwo.prototype = new TypeOne();

    var t1 = new TypeTwo();
    t1.colors.push('black');
    console.log(t1.colors);  //["red", "blue", "green", "black"]

    var t2 = new TypeTwo();
    console.log(t2.colors); //["red", "blue", "green", "black"]   

可以看,在t1这个实例中进行的colors这个属性的更改在t2这个实例中反映了出来.也就是说,所有的实例对象共享同一colors属性.

基于原型链继承的这一缺点,我们需要通过其他方式实现继承,下面来介绍几个常用的方法.

借用构造函数

在解决原型中包含引用类型值所带来问题的过程中, 开发人员开始使用一种叫借用构造函数的技术. 这种技术的基本思想相当简单, 即在子类型构造函数的内部调用超类型构造函数. 函数只不过是在特定环境中执行代码的对象, 因此, 通过使用apply()call()方法可以在新创建的对象上执行构造函数,我们通过以下代码来解决上面的问题:

function TypeOne(){
    this.colors = ['red', 'blue', 'green'];
}

function TypeTwo(){
    TypeOne.call(this);
}

TypeTwo.prototype = new TypeOne();

var t1 = new TypeTwo();
t1.colors.push('black');
console.log(t1.colors);  //["red", "blue", "green", "black"]

var t2 = new TypeTwo();
console.log(t2.colors); //["red", "blue", "green"]

混入继承

我们可以通过一个克隆函数extend(),将一组对象中的所有属性和方法克隆到一个对象中,这种实现继承的方法我们,我们将其称为混入继承.在jQuery的源码中,大量的采用了该方法.该克隆函数代码如下:

function extend (des, objs){
    for(var i = 0; i < objs.length; i++){
        for(var key in objs[i]){
            if(objs[i].hasOwnProperty(key)){
                des[key] = objs[i][key];
            }
        }
    }
}

下面,我们通过该克隆函数实现三个对象中属性和方法继承到一个对象上:

var o1 = {
    name : 'Lee_Tanghui'
}

var o2 = {
    sayHi: function (){
        console.log('你好,我是' + this.name);
    }
}

var o3 = {
    introduce: function (){
        console.log('我来自重庆');
    }
}

var obj = {};


//调用该方法实现让obj继承o1,o2,o3
extend(obj, [o1, o2, o3]);

console.log(obj.name); //Lee_Tanghui
obj.sayHi(); //你好,我是Lee_Tanghui
obj.introduce(); //我来自重庆

从上面的结果可以看到,obj对象继承了来o1,o2,o3的所有方法和属性.

组合继承

组合继承,指的是将原型链和借用构造函数的技术组合到一块. 从而发挥二者之长的一种继承模式. 其背后的思路是使用原型链实现对原型属性和方法的继承, 而通过借用构造函数来实现对实例属性的继承. 这样, 既通过在原型上定义方法实现了函数复用, 又能保证每个实例都有它自己的属性.我们可以通过以下代码来了解组合继承:

function TypeOne(name){
    this.name = name;
    this.colors = ['red', 'blue', 'green'];
}

TypeOne.prototype.sayName = function(){
    console.log(this.name);
}

function TypeTwo(name, age){
    TypeOne.call(this, name); //通过构造函数实现对实例属性的继承
    this.age = age;
}

TypeTwo.prototype = new TypeOne(); //通过原型链实现对原型属性和方法的继承


TypeTwo.prototype.sayAge = function() {
    console.log(this.age);
}

var t1 = new TypeTwo('Lee_Tanghui', 23);
t1.colors.push('black');
console.log(t1.colors);  //["red", "blue", "green", "black"]
t1.sayName(); //Lee_Tanghui
t1.sayAge(); //23

var t2 = new TypeTwo('Joe', 24);
console.log(t2.colors); //["red", "blue", "green"]
t2.sayName(); //Joe
t2.sayAge(); //24

原型式继承

原型式继承是借助一个函数,通过传递原型对象作为参数,从而创建新对象的方式实现继承.该函数由道格拉斯提出,代码源码如下:

function object(o) {
    function F(){};
    F.prototype = o;
    return new F();
}

在ECMAScript 5中新增加了Object.create()方法规范化了原型式继承.我们可以通过该方法实现将一下对象

var person = {
        name : 'joe',
        age : 24
    }

变为

[{key: "name", value: "joe" }, {key: "age", value: 24}]的数组的形式

代码实现如下

var person = {
    name : 'joe',
    age : 24,
}

//创建构造函数,用来排列键值对
function SortedList ( obj ) {
    for ( var key in obj ) {
        this.push({
            key : key,
            value : obj[ key ]
        })
    }
}

//调用Object.create()方法,继承数组的所有属性方法
SortedList.prototype = Object.create( Array.prototype );

//构造函数的实例化
var list = new SortedList( person );

console.log( list ); //[{key: "name", value: "joe" }, {key: "age", value: 24}]

Guess you like

Origin www.cnblogs.com/Irradiative/p/12177461.html