原型链和构造函数

原型链和构造函数

js每一个对象都会指向一个原型对象,并能从原型对象中继承属性。每个对象都能通过 proto 属性访问到本身原型对象。创建对象的方式不同,对象的原型也会不同。对象的原型层层指向就能构成原型链。

原型和原型链

js中最基本的对象是 Object.prototype 。js中所有的对象的原型链最后都会指向 Object.prototype 这个对象。对象字面量创建的对象的原型会直接指向 Object.prototype 。js中函数也是对象,函数的原型则不是直接指向 Object.prototype 而是直接指向 Function.prototype,Function.prototype 的原型再指向 Object.prototype(这就是一个原型链)。Number、Array这些类型也是先指向相应的原型,这个原型再指向js的标准对象(Object.prototype)。

var obj ={      //对象字面量创建的对象
    x:1
}
console.log(obj.__proto__ === Object.prototype); //true 
//普通对象原型(obj.__proto__)直接指向Object.prototype

function con(){ //函数也是对象
}
console.log(con.__proto__ === Function.prototype); //true
//任意函数原型(con.__proto__)指向Function.prototype

console.log(Function.prototype.__proto__ === Object.prototype); //true
//函数原型的原型(Function.prototype.__proto__)指向Object.prototype

//所以有下面结论
console.log(con.__proto__.__proto__ === obj.__proto__);//true
//对象实例和函数的原型都指向最终的js标准对象Object.prototype

数组、数字、字符串、布尔都有和函数一样的原型链。

console.log(Array.prototype.__proto__ === Object.prototype)     //true
console.log(String.prototype.__proto__ === Object.prototype)    //true
console.log(Number.prototype.__proto__ === Object.prototype)    //true
console.log(Boolean.prototype.__proto__ === Object.prototype)   //true

Array、String、Number、Boolean和Object这些都是构造函数,new Object() 就能实例化一个对象。总结:实例化的对象的原型指向其构造函数的prototype。除了Object()构造函数(Object已经是最基本的对象类型)构造函数的原型都指向js基本对象Object.prototype。

构造函数

js创建对象的方法最常用的就是通过对象字面量创建,这样创建的对象原型指向Object.prototype。通过Object.create()方法来创建对象,可以指定新对象原型为该方法的第一个参数而不是指向Object.prototype。构造函数创建对象也是常用的方法。通过构造函数创建对象也能够将创建的对象的原型指向任意对象。

使用Object.create()方法指定新对象的prototype。

var obj = Object.create({
    x:1
})
console.log(obj)            //Object{}
console.log(obj.x)          //1,这个值是继承下来的
console.log(obj.__proto__)  //Object {x: 1}

Object.create()方法参数必须是一个对象或null。当参数是对象时能将创建的对象的原型指向这个参数对象。所以就能从中继承属性。

js基本类型的构造函数创建对象的方法。

var arr = new Array();
console.log(arr.constructor);//function Array()

var obj = new Object();
console.log(obj.constructor);//function Object()

//字面量创建也一样
var arr2 =[];
console.log(arr2.constructor);//function Array()

构造函数

function Person(name){          //这里的Person就和Array、Number一样了,不过是我们自定义的类型。
    this.name = name;           //构造函数里的this代表新创建的对象
    this.seyHello = function(){
        console.log("Hi I am "+ this.name);
    }
}
var p = new Person("Jack");     //创建新对象
p.seyHello();                   //Hi I am Jack
console.log(p)                  //Person {name: "jack", seyHello: }
//构造函数里向this上添加的属性就会再实例化的新对象里

console.log(p.constructor === Person);//实例对象的构造函数

console.log(p.__proto__ === Person.prototype);//true

上面最后一行我们看到,实例对象的原型就是构造函数的prototype属性。所以实例化的对象会继承构造函数的prototype属性里的所有属性。

继承

由上面知到,我们可以在构造函数的prototype里添加属性,让由该构造函数实例化的对象都能继承prototype里的属性。

function Person(name){
    this.name = name;
}

Person.prototype = {
    sayhi:function () {
        console.log("Hi I am " + this.name)
    }
}

var p = new Person("Jack");
var p2 = new Person("Tom");
p.sayhi();//Hi I am Jack
p2.sayhi();//Hi Iam Tom
console.log(p);//Person {name: "Jack"}
console.log(p2);//Person {name: "Tom"}

我们将每个对象都会有的相同的方法sayhi(),放到构造函数的prototype里了。这样实例化出来的每个对象都会有这个方法。在最后两行的执行结果里我们看到实例化的对象里其实看不到sayhai这个属性。这是因为在访问对象属性时会先在对象自己的属性里寻找,如果没有找到就继续在原型里寻找,以此类推,直到最后的Object.prototype。如果在实例化的对象里添加同名属性则会覆盖原型链中的属性,但不会修改原型链中的属性。

p2.sayhi = function(){
    console.log("Hello I am "+this.name);
}

console.log(p);//Person {name: "Jack"}
console.log(p2);//Person {name: "Tom",sayhi:}, p2里添加了一个同名方法
p.sayhi();//Hi Iam Tom
p2.sayhi();//Hello Iam Tom

在p2里添加了一个同名方法p2将使用自己的方法,不再在原型链中寻找。而p没有自己的方法,只有使用原型链中的方法。上面的p和p2就是构建了原型链。以p为例,p.__proto__指向Person.prototype(即{sayhi:function(){}})。{sayhi:function(){}}指向Object.prototype。

原型运用

我们可以向constructor.prototype添加我们想给这个类型添加的方法。无论这个constructor是类似Array、Number这样的默认类型还是像上面的Person一样自定义的类型。

给数组添加一个求所有元素和的方法。

Array.prototype.getSum = function(){
    var sum =0;
    for(var i =0 ;i< this.length;i++){
        sum += this[i]
    }
    return sum;
}

var arr = new Array();
arr = [1,2,3,4];
console.log(arr.getSum());

https://github.com/songshuangfei/front-end-note/blob/master//js/prototype.md#原型链和构造函数

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值