《原型链重置版》一万多字让你读懂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

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

分析

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

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

相关文章
|
14天前
|
存储 JavaScript 前端开发
深入理解JavaScript中的事件循环(Event Loop):机制与实现
【10月更文挑战第12天】深入理解JavaScript中的事件循环(Event Loop):机制与实现
44 3
|
1天前
|
监控 JavaScript 前端开发
确定使用 `defer` 属性还是 `async` 属性来异步加载 JavaScript
【10月更文挑战第24天】选择使用 `defer` 属性还是 `async` 属性来异步加载 JavaScript 是一个需要综合考虑多个因素的决策。需要根据脚本之间的依赖关系、页面加载性能要求、脚本的功能和重要性等因素来进行权衡。在实际应用中,需要通过测试和验证来确定最适合的加载方式,以提供更好的用户体验和页面性能。
|
1天前
|
监控 JavaScript 前端开发
使用 `defer` 属性异步加载 JavaScript
【10月更文挑战第24天】使用 `defer` 属性异步加载 JavaScript 是一种有效的提高页面性能和用户体验的方法。通过合理设置 `defer` 属性,可以在不影响页面渲染的情况下异步加载脚本,并确保脚本的执行顺序。在实际应用中,需要根据具体情况选择合适的加载方式,并注意处理可能出现的问题,以确保页面能够正常加载和执行。
|
2天前
|
消息中间件 JavaScript 中间件
深入浅出Node.js中间件机制
【10月更文挑战第24天】在Node.js的世界里,中间件如同厨房中的调料,为后端服务增添风味。本文将带你走进Node.js的中间件机制,从基础概念到实际应用,一探究竟。通过生动的比喻和直观的代码示例,我们将一起解锁中间件的奥秘,让你轻松成为后端料理高手。
|
18天前
|
缓存 JavaScript 前端开发
JavaScript中数组、对象等循环遍历的常用方法介绍(二)
JavaScript中数组、对象等循环遍历的常用方法介绍(二)
24 1
|
13天前
|
JavaScript 前端开发 开发者
原型链深入解析:JavaScript中的核心机制
【10月更文挑战第13天】原型链深入解析:JavaScript中的核心机制
22 0
|
14天前
|
JavaScript 前端开发 大数据
在JavaScript中,Object.assign()方法或展开语法(...)来合并对象,Object.freeze()方法来冻结对象,防止对象被修改
在JavaScript中,Object.assign()方法或展开语法(...)来合并对象,Object.freeze()方法来冻结对象,防止对象被修改
10 0
|
18天前
|
JavaScript 前端开发 索引
JavaScript中数组、对象等循环遍历的常用方法介绍(一)
JavaScript中数组、对象等循环遍历的常用方法介绍(一)
15 0
|
6月前
|
前端开发 JavaScript
JavaScript中的原型和原型链
JavaScript中的原型和原型链
|
6月前
|
JavaScript 前端开发
【面试题】最详尽的 JS 原型与原型链终极详解(一)
【面试题】最详尽的 JS 原型与原型链终极详解(一)
133 0