欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

原型、原型链

程序员文章站 2022-05-08 16:39:14
...

一、原型

1、定义:原型是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法。

原型也是对象

2、利用原型特点和概念,可以提取公有属性。
3、对象如何查看原型   ———>隐式属性__proto__
4、对象如何查看对象的构造函数 ——>constructor    俗称构造器

下面依次举例解释一下:

1、原型是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法

例如先写一个Person的构造函数:

function Person(){
   console.log("hehe");
}

那么Person 函数的原型是  Person.protope    

因为原型也是对象,那么Person.protope = {} 就表示Person函数的祖先。

原型也可以传参,

看个具体例子吧。

Person.prototype.name = "我是Person的一个属性";
function Person(){

}
var person = new Person();

此时Person函数里面没有定义,但是当我们访问person.name 的时候出现

原型、原型链

那我们就可以发现是可以打印出来的。因为原型里面定义了name属性,当我们要访问的时候Person函数自己没有定义,它就从原型里面找name属性,有的话就打印出来。


再看一个传参例子。

Person.prototype.LastName = "Deng";
Person.prototype.say = function(){
    console.log("hehe");
}
function Person(name,age,sex){
    this.name = name;
    this.age = age;
    this.sex = sex;
}
var person = new Person('happy',18,'gril');

我们来看一下结果:

原型、原型链

2、利用原型特点和概念,可以提取公有属性

利用原型对象解决代码的冗余(代码的耦合):提取公有属性。

还是举例说明:

Car.prototype ={
    carName : "BMN",
    height : 1400,
    lang : 4900,
}
function Car(color , owner){
    this.color = color;
    this.owner = owner;
}
var car1 = new Car('red','张三');
var car2 = new Car('green', '张二');
var car3 = new Car('yellow', '张一');

原型的增删改查:不可能通过后代(对象)来改变原型,除非用Person.prototype.LastName = '123';类似的语句进行修改

3、对象如何查看原型 -——>隐式属性 __proto__

举个例子吧~

Person.prototype.name = 'abc';
function Person(){
        
}
var person = new Person();

如果我们访问person.name那么执行过程是这样的:

先在自己对象里面找name,如果找不到就沿着__proto__找原型,在原型里面找。

var this = {

__proto__ : person.prototype,

}

所以输出结果为‘abc’。


练习两个问题:

(1)

Person.prototype.name = 'sunny';
function Person(){

}
var person = new Person();
Person.prototype = {
    name : 'cherry'
}
--> person.name 结果: sunny

(2)

Person.prototype.name = 'sunny';
function Person(){

}
Person.prototype = {
    name : 'cherry'
}
var person = new Person();

 ----> person.name  结果:cherry   【预编译过程】

4、对象如何查看对象的构造函数———>constructor   俗称构造器

function Person(){

}
var person = new Person();
Car.prototype = {
    constructor : Person,
}
function Car(){

}
var car = new Car(); 

原型、原型链

二、原型链

原型链的增删改查,与原型相似,就近原则。

只有本人具有增删改查的权限,不能通过子孙进行操作

Object.create(原型)      ——————>也可以构造对象

我们可以看几道题来试一下:

Grand.prototype.__proto__  = Object.prototype;
    Grand.prototype.lastName = 'Deng';
    function Grand(){
    }
    var grand = new Grand();
    Father.prototype = Grand;
    function Father(){
        this.name = 'xuming';
        this.fortune = {
            card1 : 'visa',
        }
        this.num = 100;
    }
    var father = new Father();

    Son.prototype = father;
    function Son(){
        this.hobbit = 'smoke';
        this.num ++;
    }
    var son = new Son();

    // -----console.log(Father.num);  结果为 100
    // -----console.log(son.sum);   结果为101

此题中son不能修改father中的属性,但是father可以自己修改自己的属性;与此同理,father不能修改grand中的属性,但grand可以自行修改自己的属性。也就是说子级不能修改父级中的属性,只能通过自身修改。

再来看一道题目

    Person.prototype = {
        name : "a",
        sayName : function(){
            console.log(this.name);
        }
    }
    function Person (){
        this.name = 'b';
    }
    var person = new Person();

想一下会打印什么?【提示:sayName里面的this指向是,谁调用这个方法,this就指向谁】

结果打印b

object.create(原型)  也可用来构造对象。

var obj = Object.create(原型);

举个例子吧。

    var obj = {
            name : "sunny",
            age : 123,
        } 
        var obj1 = Object.create(obj);

那么obj1 的原型就是obj  。

原型、原型链

注意喽:绝大多数对象最终都会继承自Object.prototype

因为有Object.create(原型)来构造原型对象,所以是绝大多数,下面解释一下:

 Object.create()里面只能放原型,那如果我们在括号里面什么都不放呢?

原型、原型链

那么就会出现错误提示,对象原型只能是一个对象或null

那么我们再来试一下null的情况

原型、原型链

我们看到里面并没有原型,那么我们可以自己可以给对象添加上原型吗?

var obj = Object.create(null);

原型、原型链

我们人为给加上的原型不能用,所以说原型是系统内部的隐式属性,只能是系统给了,我们自己添不能用。

所以说全部对象最终都会继承自Object.prototype是错误的!

还有一种情况,当我们在里面加上原始值,结果会怎样?

原型、原型链

则会报错!所以原始值是不行滴。

toString

现在来说一下toString。回顾一下  undefined和null两个不能用toString   现在来解释一下为什么不能。

因为undefined 和null 不是对象,没有包装的类,所以没有原型,没有原型是不能调用toString方法的!

没有原型不能调用toString方法     【null  和   undefined】

一般调用终端object.toString (),但是有的对象原型上面就有toString方法,这时候自己重写一个toString方法就可以。

首先  123.toString();会出错,因为在数字里面那个调用的点表示浮点型,优先级最高。一般写成:

  var num = 123;
num.toString();   // ------> new Number(num).toString();
Number.prototype.toString = function(){   //方法的重写,名字相同,功能不同
 }

因为Number原型上面有toSting方法,所以就不用调用Object上面的toSting方法了。自己重写一个方法就可以。

// Object.prototype.toString
// Number.prototype.toString
// Array.prototype.toString
// Boolean.prototype.toString
// String.prototype.toString

这些数据类型上面都有toString方法。

下面看一个小例子吧。

    Number.prototype.toString = function(){
        return "hehe"
    }
    var num = 123;
    console.log(num.toString()); 
输出 :hehe



相关标签: 原型 原型链