likes
comments
collection
share

编程小白的福音:轻松学会JavaScript原型链

作者站长头像
站长
· 阅读数 2

前言

JavaScript作为一门堪称“小白诱捕器”的一门语言,其弱类型的特点属实吸引了不少的小白和爱好者尝试。但当掌握了基础语法试图更上一层楼时,JS中一些真正有趣的特点就会张牙舞爪地蹦出来,其独特的原型链机制是它的核心之一。对于新手来说,理解原型链可能会有些困难,但一旦掌握,它将成为你编写高效且可维护代码的利器。本文将介绍JavaScript原型链的基础概念,帮助你更好地理解和利用这一特性。

正文

1. 构造函数与原型

简单来说,要理解原型链其实并不困难,知名北大心理学教授完颜老师的“至理名言”——“这是一个lonely问题”很好地解释了原型链。接下来,用一些代码详细解释为何这是一个“lonely问题”

function Person() {
    this.uname = 'reader'
    this.age = 18
    this.say = function () {
        return 'hello'
    }
}

let p = new Person()

console.log(p)
编程小白的福音:轻松学会JavaScript原型链 在上面这段代码中我们定义了一个名为Person的函数,并通过这个函数实例了一个名为reader的对象,再去访问reader的属性,发现全部都能访问到,而这里访问到的属性,就是显式继承自名为Person的函数。

2. 原型链的继承

接下来让我们对各位reader动点手脚,准确来说是对Person动点手脚

 

Person.prototype.hair = 'invisible'

function Person() {
    this.uname = 'reader'
    this.age = 18
    this.say = function () {
        return '我要成为JS糕手'
    }
}

let p = new Person()

console.log(p);
console.log(p.hair)
console.log(p.say());

 

这里的prototype翻译过来就是“原型”的意思,这时我们会发现原本各位reader中没有的属性多了出来,这是为何?不仅如此,我们甚至无法通过直接展示获取到新得到的属性

编程小白的福音:轻松学会JavaScript原型链

在这个例子中,Person是一个构造函数,通过new关键字实例化了一个reader对象。构造函数的原型(Person.prototype)上定义了speak方法,这样通过p对象就可以访问到这个方法。 

但当我们直接通过log或其他的方法直接输出reader对象是看不到这些东西的,这就是隐式继承,也是和显示继承的区别之一。

 

3. 原型链的继承传承

 

原型链不仅仅是简单的属性和方法查找,它还提供了一种简单而强大的继承机制。通过正确地设置原型链,我们可以实现对象之间的共享属性和方法,提高代码的复用性。

 

 Ground.prototype.lastname=  '贺'

        function Ground(){
        }

        var ground = new Ground()

        Father.prototype = ground

        function Father() {

            this.name = 'A'
        }

        var father = new Father()

        Son.prototype = father

        function Son() {

            this.hobby = 'reading'

        }

        var son = new Son()

        console.log(son.name);

        console.log(son.lastname);

上面的代码或许会令人眼花缭乱,但是实际上也就是原型链的最好解释。祖宗(Ground)的那一辈(prototype)上有个名为lastname 的属性,值为“贺”,这个值通过原型链给到一个确定的祖宗(ground),再给到父亲这一辈(Father),再给到父亲辈中某个确定的人(father),这个lastname的值一直都在,通过一代又一代人的血脉传承,直到传到son身上。当别人问起“您贵姓”时,这个答案并非你自己决定的,而是自你的血脉诞生的那一刻起就确定好了,这也正是为什么开头说到“这是一个lonely问题”。

4. 特殊情况

当然,凡事总有意外,就算是血脉相承也总会有那么几个违背祖宗的家伙

 

function Bus() {
    this.a = 1546
}
Car.prototype = {
    constructor: Bus
    //创建者修改成功,constructor: 记录对象是由谁创建的

}
function Car() {
    this.b = 46
}

var car = new Car()

console.log(car.constructor);

 

let obj = {
            a:1
        }
       let obj2=  Object.create(null)//继承obj创造一个对象

       //网易:所有对象都会继承自 Object.prototype?(null)

 

上面两种情况一种是直接重新声明自己的构造函数,属于是“认贼作父”了,而另一种情况则更像是自己没孩子,所以根据自己的需求领养了一个,虽然没有血缘关系,但还是随了姓,其祖上传下来的属性,领养的孩子身上也会有。

编程小白的福音:轻松学会JavaScript原型链 这里还有个比较坑的地方,属于是布兰登老大哥在编写js这门语言的时候遗留下来的老bug了,因为根据原型链的查找方式,访问一个示例的对象的属性会沿着原型链往上找人家的祖宗18代的,直到找到 Object.prototype这个最早的祖先,但null不是,null和对象等引用类型的二进制编码的值都是以000开头,所以不管是typeof还是其他方法,null都会被识别为对象类型,因此在继承null创造对象是不会一路往上找到混元始祖Object.prototype的。  

结语

JavaScript原型链是这门语言中一个重要而独特的特性,虽然在初学阶段可能会觉得有些复杂,但它为我们提供了一种灵活而强大的对象模型。通过深入理解原型链,你将能够更好地利用JavaScript的面向对象编程能力,编写出结构清晰、高效可维护的代码。希望本文能够帮助你更好地掌握JavaScript原型链的精髓。