JS-原型链

原型的定义

  • 在JavaScript中,任何一个函数,都有一个prototype属性,指向一个对象。
  • 输出了一个函数的prototype属性,你会发现是一个空对象。输出这个prototype的类型,发现是object类型
  • prototype就是英语“原型”的意思。每个函数都有原型,原型是一个对象
function fun(){
	alert("Hi");
}

console.log(fun.prototype);				// Object{}
console.log(typeof fun.prototype);		// Object
	// 构造函数,构造函数里面没有任何语句,也就是说,
	// 这个构造函数在执行的时候,不会给创建出来的对象添加任何属性。
    function Person() {

    }
    // 构造函数的原型,我们更改了构造函数的原型,为一个新的对象:
    Person.prototype = {
      name: "蔡徐坤",
      sex: "男",
      age: 18
    }

    // 当一个对象被new出来的时候,不仅仅执行了构造函数里面的语句,
    // 也会把这个函数__proto__指向构造函数的Person。
    let obj= new Person();

    console.log(obj.__proto__);			// {name: "蔡徐坤", sex: "男", age: 18}
    console.log(obj.__proto__ == Person.prototype);		// true

    //当我们试图访问name、sex、age属性的时候,身上没有
    // 那么就去查找原型,原型身有,就当做了自己的属性返回了
    console.log(obj.name);		// 蔡徐坤
    console.log(obj.sex);		// 男
    console.log(obj.age);		// 18

prototype一定是函数的属性!当这个函数是一个构造函数的时候,那么它new出来的对象,将以它的原型那个对象为new出来的实例的原型对象
在这里插入图片描述

注意

任何一个对象,都有__proto__属性,这个属性指向自己的原型对象


原型的用途

定义一个方法的时候,如果写在构造函数里面:

function Person(name, age) {
    this.name = name;
    this.age = age;
    this.say = function () {
        console.log("你好,我是" + this.name + "我今年" + this.age + "岁了");
    }
}
let obj1 = new Person("菜虚鲲", 12);
let obj2 = new Person("踩墟捆", 11);
obj1.say();			// 你好,我是菜虚鲲我今年12岁了
obj2.say();			// 你好,我是踩墟捆我今年11岁了

实际上,这个函数被复制了两份,一份给了obj1,一份给了obj2, obj1和obj2这两个实例身上有了相同功能的函数,但是这个函数不是同一个函数

console.log(obj1.say == obj2.say); //false

那该如何解决这个问题呢, 一句话:所有的属性要绑在对象身上,而所有的方法定义在对象的原型对象中

function Person(name, age) {
    // 构造函数里面,负责定义一些属性,随着构造函数的执行,这些属性将绑定到new出来的对象身上
    this.name = name;
    this.age = age;
}
// 把所有的方法,定义在原型对象身上:
Person.prototype.say = function () {
    console.log("你好,我是" + this.name + "我今年" + this.age + "岁了");
}
let obj1 = new Person("菜虚鲲", 12);
let obj2 = new Person("踩墟捆", 11);
obj1.say();			// 你好,我是菜虚鲲我今年12岁了
obj2.say();			// 你好,我是踩墟捆我今年11岁了

证明了obj1的say方法和obj1的say方法,是同一个函数 , 内存消耗小很多

console.log(obj1.say == obj2.say);		// true

原型的特点

  • 存储在prototype中的方法可以被对应构造函数创建出来的所有对象共享
  • prototype中除了可以存储方法以外, 还可以存储属性
  • prototype如果出现了和构造函数中同名的属性或者方法, 对象在访问的时候, 访问到的是构造函中的数据
function Person(name, age) {
    this.name = name;
    this.age = age;
    this.currentType = "构造函数中的type";
    this.say = function () {
        console.log("构造函数中的say");
    }
}
Person.prototype = {
    currentType: "人",
    say: function () {
        console.log("hello world");
    }
}
let obj1 = new Person("菜虚鲲", 34);
obj1.say();			// 构造函数中的say
console.log(obj1.currentType);	// 构造函数中的type
let obj2 = new Person("踩墟捆", 44);
obj2.say();			// 构造函数中的say
console.log(obj2.currentType);	// 构造函数中的type
  • 在给一个对象不存在的属性设置值的时候, 不会去原型对象中查找, 如果当前对象没有就会给当前对象新增一个不存在的属性
function Person(name, age) {
    this.name = name;
    this.age = age;
}
Person.prototype = {
    constructor: Person,
    currentType: "人",
    say: function () {
        console.log("hi");
    }
}
let obj = new Person("蔡徐坤", 12);

obj.currentType = "新设置的值";

console.log(obj.currentType); // 新设置的值
console.log(obj.__proto__.currentType); // "人"

原型链

Function函数
  • JavaScript中函数是引用类型(对象类型), 既然是对象, 所以也是通过构造函数创建出来的, "所有函数"都是通过Function构造函数创建出来的对象
  • JavaScript中只要是"函数"就有prototype属性
  • Function函数"的prototype属性指向"Function原型对象"
  • JavaScript中只要是"原型对象"就有constructor属性
  • "Function原型对象"的constructor指向它对应的构造函数
  • Person构造函数是Function构造函数的实例对象, 所以也有__proto__属性
  • Person构造函数的__proto__属性指向"Function原型对象"
    在这里插入图片描述
function Person(name, age) {
    this.name = name;
    this.age = age;
}
let obj1 = new Person('踩墟捆', 12);
console.log(Function);        // ƒ Function() { [native code] }
console.log(Function.prototype);    // ƒ () { [native code] }
console.log(Function.prototype.constructor);    // ƒ Function() { [native code] }
console.log(Function === Function.prototype.constructor); // true
console.log(Person.__proto__);    // ƒ () { [native code] }
console.log(Person.__proto__ === Function.prototype); // true
Object函数
  • Object是一个函数,是系统内置的构造函数,用于创造对象的 , Object.prototype是所有对象的原型链终点
    所以,当我们在一个对象上打点调用某个方法的时候,系统会沿着原型链去寻找它的定义,一直找到Object.prototype

在这里插入图片描述

function Person(name, age) {
    this.name = name;
    this.age = age;
}
let obj1 = new Person('踩墟捆', 19);
console.log(Function.__proto__);      		// ƒ () { [native code] }
console.log(Function.__proto__ === Function.prototype);	 // true
console.log(Object);          				// ƒ Object() { [native code] }
console.log(Object.__proto__);    			// ƒ () { [native code] }
console.log(Object.__proto__ === Function.prototype);	 // true
console.log(Object.prototype);    			// {constructor: ƒ, 
__defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, 
__lookupGetter__: ƒ,}
console.log(Object.prototype.constructor);  // ƒ Object() { [native code] }
console.log(Object.prototype.constructor === Object);	 // true
console.log(Object.prototype.__proto__); 	// null
函数对象关系
  • 所有的构造函数都有一个prototype属性, 所有prototype属性都指向自己的原型对象
  • 所有的原型对象都有一个constructor属性, 所有constructor属性都指向自己的构造函数
  • 所有函数都是Function构造函数的实例对象(Function函数是所有函数的祖先函数)
  • 所有函数都是对象, 包括Function构造函数
  • 所有对象都有__proto__属性
  • 普通对象的__proto__属性指向创建它的那个构造函数对应的"原型对象"
  • 所有对象的__proto__属性最终都会指向"Object原型对象"
  • "Object原型对象"的__proto__属性指向NULL
    在这里插入图片描述
function Person(name, age) {
    this.name = name;
    this.age = age;
}
let obj1 = new Person('踩墟捆', 12);
console.log(Function.prototype.__proto__);      // Object
console.log(Person.prototype.__proto__);        // Object
console.log(Function.prototype.__proto__ === Person.prototype.__proto__);   // true
console.log(Function.prototype.__proto__ === Object.prototype);  			//true
console.log(Person.prototype.__proto__ === Object.prototype);   			// true
原型链机制
  • 对象中__proto__组成的链条我们称之为原型链
  • 对象在查找属性和方法的时候, 会先在当前对象查找
  • 如果当前对象中找不到想要的, 会依次去上一级原型对象中查找 , 如果找到Object原型对象都没有找到, 就会报错

在这里插入图片描述

function Person(name, age) {
    this.name = name;
    this.age = age;
    this.currentType = "构造函数中的type";
}
Person.prototype = {
    // 注意点: 为了不破坏原有的关系, 在给prototype赋值的时候
    // 需要在自定义的对象中手动的添加constructor属性, 手动的指定需要指向谁
    constructor: Person,
    // 构造函数中的属性或方法会替换原型对象中的属性或方法
    currentType: "人",
    say: function () {
       console.log("Hi");
    }
}
let obj1 = new Person("lnj", 34);

console.log(obj1.currentType);			// 构造函数中的type
console.log(Person.prototype.constructor);		// ƒ Person(name, age) {...}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值