《原型链重置版》一万多字让你读懂JavaScript原型对象与原型链的继承,探秘属性的查找机制! (1)

简介: 为什么要使用原型!

logo.png

前言

有些新手朋友可能听说过这么一句话,就是js中存在两个链条,它们分别为:作用域链原型链

它们彼此的区别在于作用域链是为了访问变量数据而存在的一种链条访问机制

原型链是访问对象属性或者方法而存在的一种机制!

其中这里的原型链就是今天我要说的主题!

我们学习js必须要知道什么是原型、原型链、构成函数、实例对象这些彼此之间的关系和应用范围!

如果你没有搞明白js中的原型链也就说明你没有把js学明白!

那么接下来就跟着我一起开始学习吧!

为什么要使用原型?

原型js中也称之为原型模式, 那么为什么要有这种模式存在呢?

因为我们js面向对象不是说过吗?面向对象编程其实就是一种模块、一种封装对吧!

如果你还没有完全明白javascript面向对象建议你一定要听我讲完下面的知识点!

构造函数模式

有的时候我们会使用构造函数模式创建对象

虽然这种构造函数创建对象,看起来没什么大问题,但是并非没有缺点!

这里我们来看一段简单的构造函数模式创建对象的案例吧!

代码

function Person(username,age,job){
   
   
    this.username=username;
    this.age=age;
    this.job=job;
    this.say=function (){
   
   
        console.log('我的名字叫:'+this.username+',年龄:'+this.age+',职业:'+this.job);
    }
}

var test=new Person('张三',18,'ui设计师');
test.say();

这就是一段非常简单的构造函数模式封装对象的方法!

构造函数模式的缺点

任何一种技术的出现,都是为了弥补旧技术的不足!

那么构造函数模式有什么缺点呢?为什么又要搞出一个原型模式呢? 搞出这么个东西意义何在?

这里我先卖个关子,想知道的话就继续往下看吧! 😛😛😛

从上面的代码角度上看,确实感觉不出什么奇怪之处!

那我们再来看一个构造函数模式的例子:

代码

//构造函数
function Person(){
   
   
    this.say=function (num){
   
   
        console.log('测试方法'+num);
    }
}
//实例化
var obj_1=new Person();
var obj_2=new Person();

//调用
obj_1.say(1);
obj_2.say(2);

console.log(obj_1.say===obj_2.say);   //返回false

然后我们看看下面这张图你就知道其中缺点在什么地方了!

如图

structure-1.png

此时你会发现,这个函数居然会不相等!! 为什么呢?

从另一个角度来讲构造函数每执行一次就会把构造函数中的方法也重新在内存中生成一份相同的方法!

比如: 执行一万次构造函数,那么就会在内存中创建一万次构造函数里面的方法, 这对内存是一种非常大的消耗

要知道在ECMAScript中只要是函数都是对象 这句话!

之所以会返回false就是因为函数的底层地址是不一样的! 不要以为方法名称一样就是一样! 那你就错了

如图

structure-2.png

并且函数本身也是对象, 你定义一个函数,也就相当于实例化了一个函数对象, 其实就会在内存中开辟一个空间,地址也会不一样!

上面的这行代码

this.say=function (num){
   
   
    console.log('测试方法'+num);
}

其实从一定逻辑上讲也可以看成以下形式

this.say=new Function (num){
   
   
    console.log('测试方法'+num);
}

这样子其实你更好理解每个构造函数实例中的方法,其实是不同Function的实例

所以说像这种在内存中无限创建很多完成同样方法的Function实例是完全没有必要的!

那么有没有什么好的方案可以解决这个问题呢?

我们完全可以使所有的对象共享同一个方法,那么构造函数执行一万次,在内存中也只会存在一份相应的方法!

通常是可以把这个函数方法转移到构造函数外部

代码说明

function Person(username,age,city){
   
   
    this.name=username;
    this.age=age;
    this.city=city;
    this.say=say;
    /*this.say=function() {
         console.log(this.name+'的年龄是:'+this.age);
     }*/
}

//把say方法写在全局作用域中
function say() {
   
   
    //这里的this要清楚是谁在调用say这个方法 this自然就指向谁
    console.log(this.name+'的年龄是:'+this.age);
}
var test1=new Person('张三',33,'北京市');
var test2=new Person('李四',66,'深圳市');

//判断test1与test2之间的方法是否是共用的
console.log(test1.say==test2.say);

如图

structure-3.png

案例2

以下案例也是同样的道理!

//构造函数
function Person(){
   
   
    this.say=say;
}

//定义到全局下
function say(num){
   
   
    console.log('测试方法'+num);
}

//实例化
var obj_1=new Person();
var obj_2=new Person();

//调用
obj_1.say(1);
obj_2.say(2);

console.log(obj_1.say===obj_2.say);   //返回true

目的我们是达到了,但是这样写就真的行了吗? 不会存在其他问题吗?

分析

很明显在开发当中 如果把函数这样子写在全局作用域中,在多人开发的时候那么就会出现命名冲突,或者说这样做会 污染全局作用域的命名空间, 所以说我们在项目开发的时候都是尽量地不在全局作用域中写变量和函数

那么如何来解决这样的问题呢? 就是接下来我要说的原型和原型链,然后根据情况来解决相应的问题!

相关文章
|
1月前
|
JavaScript 前端开发
如何在 JavaScript 中使用 __proto__ 实现对象的继承?
使用`__proto__`实现对象继承时需要注意原型链的完整性和属性方法的正确继承,避免出现意外的行为和错误。同时,在现代JavaScript中,也可以使用`class`和`extends`关键字来实现更简洁和直观的继承语法,但理解基于`__proto__`的继承方式对于深入理解JavaScript的面向对象编程和原型链机制仍然具有重要意义。
|
1月前
|
Web App开发 JavaScript 前端开发
如何确保 Math 对象的方法在不同的 JavaScript 环境中具有一致的精度?
【10月更文挑战第29天】通过遵循标准和最佳实践、采用固定精度计算、进行全面的测试与验证、避免隐式类型转换以及持续关注和更新等方法,可以在很大程度上确保Math对象的方法在不同的JavaScript环境中具有一致的精度,从而提高代码的可靠性和可移植性。
|
1月前
|
JSON 前端开发 JavaScript
JavaScript中对象的数据拷贝
本文介绍了JavaScript中对象数据拷贝的问题及解决方案。作者首先解释了对象赋值时地址共享导致的值同步变化现象,随后提供了五种解决方法:手动复制、`Object.assign`、扩展运算符、`JSON.stringify`与`JSON.parse`组合以及自定义深拷贝函数。每种方法都有其适用场景和局限性,文章最后鼓励读者关注作者以获取更多前端知识分享。
18 1
JavaScript中对象的数据拷贝
|
1月前
|
JavaScript 前端开发
如何使用原型链继承实现 JavaScript 继承?
【10月更文挑战第22天】使用原型链继承可以实现JavaScript中的继承关系,但需要注意其共享性、查找效率以及参数传递等问题,根据具体的应用场景合理地选择和使用继承方式,以满足代码的复用性和可维护性要求。
|
1月前
|
JavaScript 前端开发 开发者
js实现继承怎么实现
【10月更文挑战第26天】每种方式都有其优缺点和适用场景,开发者可以根据具体的需求和项目情况选择合适的继承方式来实现代码的复用和扩展。
31 1
|
7月前
|
前端开发 JavaScript
JavaScript中的原型和原型链
JavaScript中的原型和原型链
104 0
|
7月前
|
JavaScript 前端开发
【面试题】最详尽的 JS 原型与原型链终极详解(一)
【面试题】最详尽的 JS 原型与原型链终极详解(一)
148 0
|
7月前
|
JavaScript 前端开发
手把手教你学会js的原型与原型链,猴子都能看懂的教程
手把手教你学会js的原型与原型链,猴子都能看懂的教程
|
7月前
|
JavaScript 前端开发
JavaScript原型,原型链
JavaScript原型,原型链
|
6月前
|
设计模式 JavaScript 前端开发
【JavaScript】深入浅出JavaScript继承机制:解密原型、原型链与面向对象实战攻略
JavaScript的继承机制基于原型链,它定义了对象属性和方法的查找规则。每个对象都有一个原型,通过原型链,对象能访问到构造函数原型上的方法。例如`Animal.prototype`上的`speak`方法可被`Animal`实例访问。原型链的尽头是`Object.prototype`,其`[[Prototype]]`为`null`。继承方式包括原型链继承(通过`Object.create`)、构造函数继承(使用`call`或`apply`)和组合继承(结合两者)。ES6的`class`语法是语法糖,但底层仍基于原型。继承选择应根据需求,理解原型链原理对JavaScript面向对象编程至关重要
153 7
【JavaScript】深入浅出JavaScript继承机制:解密原型、原型链与面向对象实战攻略
下一篇
DataWorks