首页 » PHP教程 » php原型链技巧_一篇JavaScript技能栈带你理解持续和原型链

php原型链技巧_一篇JavaScript技能栈带你理解持续和原型链

访客 2024-11-29 0

扫一扫用手机浏览

文章目录 [+]

那么是哪些呢?详细的三大特性指的是什么?请记住三大特性:封装(Encapsulation),继续(Inheritance),多态(Polymorphism)。
我们常说的封装,继续,多态,三大特点。
六大原则指:单一职责原则(SRP),开放封闭原则(OCP),里氏更换原则(LSP),依赖颠倒原则(DIP),接口分离原则(ISP),最少知识原则(LKP)。

继续的理解:

php原型链技巧_一篇JavaScript技能栈带你理解持续和原型链

继续,如果有很多的类,每个类中的属性或者是方法都不一样,也有些属性或者方法都是相同的,以是如果去定义它们,有时候要重复去定义这些相同的属性或者方法。

php原型链技巧_一篇JavaScript技能栈带你理解持续和原型链
(图片来自网络侵删)

这就导致了代码重复性,这就导致了继续的涌现,继续便是儿子继续老子的基因一样,让一个类“儿子类”继续它们的“父亲”,这样就可以拥有“父亲”的所有具有相同的属性或者是方法了。
这样的类我们称为它叫做“父类”,继续顾名思义便是儿子继续老子,具有老子的属性或者是方法,通过这种的继续办法,让所有的子类都可以访问这些属性或者是方法,而不用每次都在子类中去定义这些属性或者是方法咯,多方便,多快捷,多快好省!

实在JavaScript并不是什么强面向工具措辞,由于它的灵巧性决定了并不是所有面向工具的特色都适宜JavaScript的开拓。

我们实在讲到了类,那么类又是怎么理解的呢?

类是什么呢?类是具有属性或者是方法的凑集,可以通过类的布局函数创建一个实例的工具。
说人话便是,如把人类看做一个类,而我们每一个人便是一个实例的工具,类的实例工具包含两方面:

类的所有非静态(属性或者是方法)

类的所有静态(属性或者是方法)

非静态(属性或者是方法)便是每一个实例的特有的,属于个性。

所有静态(属性或者是方法)便是每一个实例的共性的,属于共性。

我自己是一名从事了多年开拓的web前端老程序员,目前辞职在做自己的web前端私人定制课程,今年年初我花了一个月整理了一份最适宜2019年学习的web前端学习干货,各种框架都有整理,送给每一位前端小伙伴,想要获取的可以关注我的头条号并在后台私信我:前端,即可免费获取。

说人话便是,个性(非静态)便是每个人的名字都是不相同的,而名字这个属性就是非静态属性;共性(静态)便是每个人都是要用饭的,而用饭这个方法便是静态方法。

那么在JavaScript中的类是如何实现的呢?

类的实现:

利用函数创建类,利用new关键字就可以天生实例工具;利用布局函数实现非静态(属性或者是方法),利用prototype实现静态(属性或者是方法)。

// 创建函数function dashucoding() { console.log('dashucoding')}// 函数赋值var da = dashucoding() // undefined// 实例工具var jeskson = new dashucoding() // {}

个中dashucoding是一个普通函数,也是一个类的布局函数,当调用dashucoding()的时候,它作为一个普通函数会被实行,会输出dashucoding,因没有返回值,就会返回undefined;而当调用new dashucoding()时,会输出dashucoding并且返回一个工具。

我们把dashucoding这个函数来布局工具,以是我们把这个dashucoding看作布局函数。
布局工具,布局函数。
即通过利用函数,定义布局函数,就相称于定义一个类,通过new关键字,天生一个实例工具。

// 布局函数function dashucoding(name) { this.name = name}var da1 = new dashucoding('jeskson');var da2 = new dashucoding('jeckson');console.log(da1.name) // jesksonconsole.log(da2.name) // jeckson

个中dashucoding布局函数中多个参数,函数体中多this.name=name,这句中的this指向new关键字返回的实例化工具。

根据布局函数中参数不同,天生的工具中具有的属性name值也是不同的,这里的name是什么呢?看的出来吗?便是这个类的非静态(属性或者方法)。

那么如何利用prototype来实现静态呢?(原型链的知识点)

原型工具链,原型链,JavaScript内建的继续方法被称为原型工具链,又称为原型工具继续。
有这样一句话,对付一个工具,由于它继续了它的原型工具的属性,以是它可以访问到这些属性,而原型工具也是一个工具,同理,它也可以有自己的原型工具,以是也是可以继续它的原型工具的属性。

what?一脸懵逼,是不是没听懂,我以为如小白,鬼听得懂。
原型继续链观点,工具继续其原型工具,而原型工具继续它的原型工具。
这观点说得鬼听得懂哦,what?what?what?赏你一大嘴巴子,你妈妈买菜必涨价,超级更加。
你爷爷下象棋,必备指指示点。

原型链:prototype?类的prototype是什么?工具的proto是什么?

类中的prototype

被称作原型:在JavaScript中,每当我们定义一个布局函数时,JavaScript引擎中就会自动为这个类添加一个prototype。

在JavaScript中,当我们利用new来创建一个工具的时候,JavaScript引擎就会自动为这个工具添加一个__proto__属性,并指向其类的prototype。

// 布局函数function dashucoding(name) { // 非静态属性 this.name = name;}// 每当我们定义一个布局函数,JavaScript引擎就会自动为这个// 类中添加一个prototypeconsole.log(dashucoding.prototype)var da1 = new dashucoding('jeskson');var da2 = new dashucoding('jeckson');// 工具的protoconsole.log(da1.__proto__);console.log(da2.__proto__);console.log(dashucoding.prototype === da1.__proto__);// trueconsole.log(dashucoding.prototype === da2.__proto__);// true

个中dashucoding.prototype是一个工具,dashucoding类的实例化工具da1,da2都有一个属性__proto__,也是工具。
并dashucoding.prototype即是da1或者da2的__proto__。

在JavaScript中引用类型的相等意味着它们所指向的都是同一个工具,任何一个实例化工具的__proto__属性都指向其类的prototype。

工具中的__proto__属性:

// 工具赋值var pro = { name: 'jeskson';}var person = { __proto__: pro}console.log(person.name) // jesksonperson.name = 'jeckson'console.log(person.name) // jeckson

瞥见没,个中的person并没有定义name属性,而console.log出来的结果是jeskson哦,这是为啥呢?这便是所谓JavaScript中最厉害牛逼的原型链结果。

实在我们回去看代码就知道是有关联的关系的,person中属性__proto__的值为pro,个中的pro指向pro这个工具,pro中的属性具有name:'jeskson'的,也有__proto__属性,值为Object,而Object指向Object,Object的属性也是有__proto__属性,其值为null。

来,接下来,让我们更加懂的说一下情形,当我们访问person.name是,个中的过程是什么样的?

当我们person.name进行访问的时候,可以看到我们并没有写name这个属性,首先,person.name会去找工具中是否有这个name属性,如果没有,它就会去找__proto__属性工具。
看到没,在person中是有这个__proto__属性的,别说没有?

没有,你便是没仔细阅读文章,没有,你便是没看文章内容,没有,你便是不适宜。

person中__proto__属性工具的值是pro工具,以是person的__proto__指向了pro这个工具,那么就会创造在pro这个工具中具有name这个属性,那么就可以返回个中的值为'jeskson'了。

但是如果我们给person加上了这个name属性的,先看代码我们是不是给它加了name值,这时候我们console.log中的person.name值就不会找__proto__这个属性了,会去先找个中的name属性,值为'jeckson',以是打印返回的'jeckson'。

这里重点说一个:pro的__proto__指向是Object,每个工具中都有__proto__属性,这个属性指向创建出来的工具它们默认是Object类的工具,以是记住工具的属性__proto__自然指向Object.prototype。

好了好了,那么读懂了原型链,就来说上面没说的,利用prototype实现静态(属性或者是方法)。

// 利用prototype实现静态(属性或者方法)// 布局函数function dashucoding(name) { this.name = name;}// 利用prototype实现静态(属性或者是方法)// 创建了方法dashucoding.prototype.eat = function() { console.log('i eat');}// 实例工具var da1 = new dashucoding('jeskson');var da2 = new dashucoding('jeckson');// 给这个人添加方法da1.eat() // i eatda2.eat() // i eatconsole.log(da1.eat === da2.eat) // true

个中一句:dashucoding.prototype.eat = function(){...},通过dashucoding实例化的工具__proto__都会指向dashucoding.prototype。

原型链的知识点,只要布局函数中没有定义同名的非静态(属性或者是方法),那么每个工具进行访问的时候都是访问其内部找到的eat方法,这样我们就利用原型链,实现了类的静态(属性或者是方法)。

// 布局函数function dashucoding(name) { this.name = name; eat() { console.log('i eat'); }}// 这便是同名

工具的继续,利用工具字面量创建工具时,会隐式的指向Object.prototype为新工具的[[Prototype]],利用Object.create()方法创建工具时,会显示指定新工具的[[Prototype]]。
Object.create()方法接管两个参数,第一个参数为新工具的[[Prototype]],第二个参数描述了新工具的属性。

又是懵逼了!


// 工具字面量形式var da = { name: 'jeskson'}// 原型被隐式地设置为Object.prototype形式了,这就懂了// Object.create()创建,显示指定了Object.prototypevar dada = Object.create(Object.prototype, { dashucoding: { id: '123', code: 'dashucoding', value: '前端' }})

请把以上代码记住,牢牢记住。
实现工具的继续:

请把以上代码记住,牢牢记住。
实现工具的继续:

原型链继续:

原型链是JavaScript实现继续的紧张方法,其基本思想是利用原型让一个引用类型继续另一个引用类型的属性和方法。
实现原型链的基本模式是,让当前布局函数的原型工具即是另一个布局函数的实例。

function A(name, age) { this.name = name; this.age = age; this.family = ["爸爸","妈妈"]; if(typeof(this.getName) != "function") { A.prototype.getName = function() { return this.name; } }}function B() { this.job = 'IT'; if(typeof(this.getJob) != "function") { B.prototype.getJob = function() { return this.job; } }}B.prototype = new A("jeskson", 12);var da = new B();// 实例da 的属性name,age是继续自原型B。
prototypeconsole.log(da.name); // jesksonconsole.log(da.age); // 12console.log(da.hasOwnProperty("name")); // falseconsole.log(da.hasOwnProperty("age")); // false// 实例da的原型B.prototype被重写,以是da的布局函数指向Aconsole.log(da.constructor == B);console.log(da.constructor == A);// 输出 false, true// 一个完全的原型链// da.__proto__ > B.prototype.__proto__ > A.prototype.__proto__ > Object.prototypeconsole.log(B.prototype.isPrototype(da));// truecosole.log(A.prototype.isPrototype(B.prototype));// trueconsole.log(Object.protoype.isProtypeOf(A.prototype));// true

原型链继续:

JavaScript中的工具继续是布局函数根本的根本,险些所有的函数都有prototype属性,除了通过Function.prototype.bind方法布局出来的函数是个例外,它是可以被更换和修正的。

原型链实现继续,让子类继续父类的静态(属性或者是方法)

// 父类function Father() {}Father.prototype.say = function() { console.log('father')}function Son() {}var son1 = new Son();console.log(son1.say); // undefined// 原型链实现继续的关键代码Son.prototype = new Father();var son2 = new Son();console.log(son2.say) // function(){...}

当我们利用Son.prototype = new Father()后,通过new Sow()天生的工具都会有__proto__属性,这个属性指向Son.prototype。
实现了子类继续了父类的静态(属性或者是方法)。

JavaScript中的原型和原型链:

prototype,当我们创建的每一个函数都有一个prototype原型属性,这个属性便是一个指针,指向了一个工具,而这个工具的用场便是可以由特定类型的所有实例共享的属性和方法。
利用原型的好处便是可以让所有的工具实例共享原型工具所包含的属性和方法。

function da(){}da.prototype.name = 'jeskson';da.prototype.age = 12;da.prototype.job = 'it';da.prototype.sayName = function() { alert(this.name);}var person1 = new da();person1.sayName(); // jesksonvar person2 = new da();person2.sayName(); // jesksonalert(person1.sayName() === person2.sayName());// true

da.prototype指向原型工具,da.prototype.constructor指向da,默认创建一个新函数,它的原型工具只包含constructor属性,da工具的实例的内部属性仅仅指向da.prototype

__proto__,所有的工具都具有__proto__属性,隐式原型,指向布局该工具的布局函数的原型工具。

function da() {}da.prototype.name = 'jeskson';da.prototype.age = 12;da.prototype.job = 'it';da.prototype.sayName = function() { alert(this.name);}// 实例化工具var person1 = new da();console.log(da);// da(){}console.log(da.prototype);console.log(da.prototype.__proto__);console.log(da.prototype.constructor);console.log(person1);console.log(person1.__proto__);

原型链:当为工具实例添加一个属性的时候,这个属性会屏蔽掉原型工具中的同名工具。

function da() {}da.prototype.name = 'jeskson';da.prototype.age = 12;da.prototype.job = 'it';da.prototype.sayName=function() { alert(this.name);}var person1 = new da();console.log(person1.name); // jeskonperson1.name="jeckson"console.log(person1.name); // jecksonperson1.name = nullconsole.log(person1.name); // nulldelete person1.name // 删除,实例属性,把稳实例属性console.log(person1.name); // jeskson

布局函数有一个prototype属性,指向的是实例工具的原型工具,原型工具有一个constructor属性,指向的是原型工具对应的布局函数,实例工具有一个__proto__属性,指向的是该实例工具对应的原型工具。

原型方法:

isPrototypeOf()方法用来判断,某个prototype工具和某个实例之间的关系:

alert(Cat.prototype.isPrototypeOf(cat1)); //truealert(Cat.prototype.isPrototypeOf(cat2)); //true

hasOwnProperty()方法,每个实例工具都有一个hasOwnProperty()方法,用来判断某一个属性到底是本地属性,还是继续prototype工具的属性。

alert(cat1.hasOwnProperty("name")); // truealert(cat1.hasOwnProperty("type")); // false

in运算符,用来判断某个实例是否含有某个属性,不管是不是本地属性。

alert("name" in cat1); // truealert("type" in cat1); // true

布局函数,原型,实例之间的关系:

布局函数,是创建工具的一种常用的办法,其他创建工具的办法还包括工厂模式,原型模式,工具字面量等,我们来看一个大略的布局函数。

// 布局函数function Da(name, age) { // 布局函数的命名约定第一个字母利用大写的形式 this.name = name; this.age = age;}

每一个布局函数都有一个prototype属性,Da.prototype属性实在是一个指针,指向一个工具,该工具拥有一个constructor属性,以是布局函数中的prototype属性指向一个工具。

原型:

无论什么时候,只要创建一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,这个属性指向函数的原型工具,在默认情形下,所有原型工具都会自动得到一个constructor()布局函数,这个属性包含一个指向prototype属性所在函数的指针。

一脸懵逼中!


布局函数与原型的关系

布局函数中有prototype属性,指向原型工具中constructor,原型工具中有constructor()布局函数,在原型工具中这个constructor指向布局函数中所在指针。

原型:布局函数的prototype属性所指向的工具。
(原型工具)

原型这个工具中,有一个constructor属性又指回布局函数本身。

function Da(name,age) { this.name = name; this.age = age;} var da = new Da('jeskson', '12');

通过布局函数创建工具的过程叫做实例化,创建出来的工具叫做实例

为原型添加一个方法:

Da.prototype.eat = function() { console.log('i eat');}

在实例中调用该方法:

var da = new Da('jeskson', '12');da.eat(); // i eat

原型中的属性和方法,在连接到其对应的布局函数的实例上,是可以利用的。

布局函数,实例,原型 的关系

布局函数里有什么?

布局函数里有prototype

原型里有什么?

原型里有constructor,eat()方法

实例里有什么?

实例有属性或者是方法

最好的实例代码:

// 创建 Da1 布局函数function Da1 () { this.name = 'jeskson';}// 给Da1布局函数的原型添加方法Da1.prototype.eat1 = function() { console.log('i eat da1');}// 创建Da2布局函数function Da2 () { this.name = 'jeckson';}// 将Da1的实例工具直接赋值给D2的原型Da2.prototype = new Da1();// 给Da2的原型添加一个方法Da2.prototype.eat2 = function() { console.log('i eat da2');}// 实例化Da2var da2 = new Da2();da2.eat1(); // jeskson

原型链继续,函数声明创建函数时,函数的prototype属性被自动设置为一个继续自Object.prototype的工具,该工具有个自己的属性constructor,其值便是函数本身。

// 布局函数function Da() {}// JavaScript引擎Da.prototype = Object.create(Object.prototype, { constructor: { name: true, age: true }});console.log(Da.prototype.__proto__ === Object.prototype);// true

创建出来的布局函数都继续自Object.prototype,JavaScript引擎帮你把布局函数的prototype属性设置为一个继续自Object.prototype的工具。

布局函数实现继续,让子类继续了父类的非静态(属性或者是方法)

// 布局函数function Da(name) { this.name = name}function Son() { Da.apply(this, agruments) this.sing = function() { console.log(this.name); }}var obj1 = new Son('jeskson');var obj2 = new Son('jeckson');obj1.sing(); // jesksonobj2.sing(); // jeckson

组合办法实现继续,原型链继续和布局函数根本,实现对父类的静态及其非静态的(属性或者是方法)的继续。

function Father(name) { this.name = name}Father.prototype.sayName = function() { console.log(this.name);}function Son() { Father.apply(this, arguments)}Son.prototype = new Father();var son1 = new Son('jeskson');var son2 = new Son('jeckson');son1.sayName(); // jesksonson2.sayName(); // jeckson

寄生组合办法实现继续:Super函数,让Father的原型寄生在Super的原型上,让Son去继续Super,然后把这个过程放到一个闭包内。

// 布局函数function Father(name) { this.name = name}Father.prototype.sayName = function() { console.log(this.name);}function Son() { Father.apply(this,arguments)}(function() { function Super(){} Super.prototype = Father.prototype Son.prototype = new Super()}())var son1 = new Son('jeskson');

子类型布局函数的内部调用父类布局函数

function getArea() { return this.length this.width}/ 四边形 /function Rectangle(length, width) { this.length = length this.width = width}/ 获取面积 /Rectangle.prototype.getArea = getArea/ 获取尺寸信息 /Rectangle.prototype.getSize = function() { console.log(`Rectangle: ${ this.length }x${ this.width },面积: ${ this.getArea() }`)}/ 正方形 /function Square(size) { Rectangle.call(this, size, size) this.getArea = getArea this.getSize = function() { console.log(`Square: ${ this.length }x${ this.width },面积: ${ this.getArea() }`) }}var rect = new Rectangle(5, 10)var squa = new Square(6)rect.getSize() // Rectangle: 5x10,面积: 50squa.getSize() // Square: 6x6,面积: 36

面向工具,创建工具,利用布局函数创建

var obj = new Object();

字面量创建:

var obj = {};

工厂模式:

var p1 = new Object();p1.name = 'da';p1.age = '12'p1.showName = function() { return this.name}var p2 = new Object();p2.name = 'da2';p2.age = '23',p2.showName = function() { return this.name}

采取工厂模式,抽象创建工具的过程,封装相同的属性或者是方法

function createF(name, age) { var obj = new Object(); obj.name = name; obj.age = age; obj.showName = function() { return this.name; }; return obj;}var p1 = createF('jeskson',12);var p2 = createF('jeckson',23);

布局模式:

function Person(name, age) { this.name = name; this.age = age; this.showName = function() { console.log(this.name); }}var p1 = new Person('张三', '1');var p2 = new Person('李四', '2');

什么是原型链:

在JavaScript中继续的紧张方法便是通过原型链,紧张是一个原型工具即是另一个类型的实例,由于实例内部含有一个指向布局函数的指针,相称于重写了该原型工具,此时该原型工具包含了一个指向另一个原型的指针。
原型链的底层是:Object.prototype.__proto__,值为null。

JavaScript只有一种构培养是工具,每个实例工具都有一个私有的属性为__proto__,它的指向它的布局函数的原型工具(prototype)。
该原型工具也有一个自己的原型工具__proto__,层层向上直到一个工具的原型工具为null。

基于原型链的继续,JavaScript工具有一个指向一个原型工具的链,Object.prototype属性表示Object的原型工具。

let f = function() { this.a = 1; this.b = 2;}// function f() { this.a = 1; this.b = 2;}//let o = new f(); // {a:1,b:2}f.prototype.b=3;f.prototype.c=4;

当继续的函数被调用时,this指向的是当前继续的工具,而不是继续的函数所在的原型工具。

var o = { a: 2, m: function() { return this.a+1; }};console.log(o.m()); // 3当调用o.m时,'this'指向了ovar p = Object.create(o);// p是一个继续自o的工具p.a = 4;console.log(p.m());function doSomething(){}doSomething.prototype.foo = "bar";console.log( doSomething.prototype );

利用Object.create创建工具

var a = {a: 1}; // a ---> Object.prototype ---> nullvar b = Object.create(a);// b ---> a ---> Object.prototype ---> nullconsole.log(b.a); // 1 (继续而来)var c = Object.create(b);// c ---> b ---> a ---> Object.prototype ---> nullvar d = Object.create(null);// d ---> nullconsole.log(d.hasOwnProperty); // undefined, 由于d没有继续Object.prototype

关于目前文章内容即涉及前端,PHP知识点,如果有兴趣即可关注,很荣幸,能被您创造,真是慧眼识英!
也感谢您的关注,在未来的日子里,希望能够一贯默默的支持我,我也会努力给大家分享更多精良的作品。
我们一起发展,从零根本学编程,将 Web前端领域、数据构造与算法、网络事理等普通易懂的呈现给小伙伴。
分享 Web 前审察干的技能文章、工具资源、精选课程、热点资讯。

原文链接:https://mp.weixin.qq.com/s/PvMeSiEb38UmpwglgPa9fw作者:达达前端小酒馆

标签:

相关文章

执业药师试卷代码解码药师职业发展之路

执业药师在药品质量管理、用药安全等方面发挥着越来越重要的作用。而执业药师考试,作为进入药师行业的重要门槛,其试卷代码更是成为了药师...

PHP教程 2025-02-18 阅读1 评论0

心灵代码主题曲唤醒灵魂深处的共鸣

音乐,作为一种独特的艺术形式,自古以来就承载着人类情感的表达与传递。心灵代码主题曲,以其独特的旋律和歌词,唤醒了无数人的灵魂深处,...

PHP教程 2025-02-18 阅读0 评论0

探寻福建各市车牌代码背后的文化内涵

福建省,地处我国东南沿海,拥有悠久的历史和丰富的文化底蕴。在这片充满魅力的土地上,诞生了许多具有代表性的城市,每个城市都有自己独特...

PHP教程 2025-02-18 阅读1 评论0

探寻河北唐山历史与现代交融的城市之光

河北省唐山市,一座地处渤海之滨,拥有悠久历史和独特文化的城市。这里既是古丝绸之路的起点,也是中国近代工业的发源地。如今,唐山正以崭...

PHP教程 2025-02-18 阅读0 评论0