ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

JS原型链模式和继承模式

2020-09-10 13:03:55  阅读:266  来源: 互联网

标签:function console log 模式 JS getX 原型 prototype Fn


原型链模式

实例识别:
构造函数模式中拥有了类和实例的概念,并且实例和实例之间是相互独立开的

function CreateJsPerson(name, age){
    this.name = name;
    this.age = age;
}
CreateJsPerson.prototype.writeJs = function(){
        console.log("my name is " + this.name + ", i can                write js ~~")
    }

基于构造函数模式的原型模式解决了,方法或者属性共有的问题,想让谁共有就把他放在CreateJsPerson.prototype上即可

js中规定的

prototype

  1. 每一个函数数据类型(普通函数,类)都有一个天生自带的属性:prototype(原型),并且这个属性是一个对象数据类型的值

constructor

  1. 并且在prototype上浏览器天生给它加了一个属性constructor(构造函数),属性值是当前函数(类)本身

_ proto _

  1. 每一个对象数据类型(普通的对象,实例,prototype..)也天生自带一个属性: _ _proto _ _,属性值是当前实例所属类的原型(prototype)
function Fn(){
    this.x = 100;
}
Fn.prototype.getX = function(){
    console.log(this.x);
}
var f1 = new Fn;
var f2 = new Fn;

console.log(Fn.prototype.constructor === Fn); // true
console.log(f1 instanceof Object); // true
  • f1 instanceof Object -> true 因为f1通过_ _ protp _ _ 可以向上级查找,不管查找多少级都可以查找到Object
  • 在Object.prototype上没有_ _protp _ _ 这个属性
    5780d495bccfd76c04ed1ad6e283a75b.png

原型链查找机制

  1. 通过 对象名.属性名 的方式获取属性值的时候, 首先在对象的私有的属性上进行查找, 如果私有中存在这个属性,则获取的是私有的属性值;
  2. 如果私有的没有,则通过__proto__找到所属类的原型, 类的原型上定义的属性和方法都是当前实例公有的属性和方法, 原型上存在的话, 获取的是共有的属性值;
  3. 如果原型上也没有,则继续通过原型上的__proto__继续向上查找, 一直找到Obejct.prototype为止
console.log(f1.getX === f2.getX); // true
console.log(f1.__proto__.getX === f2.getX);// true
console.log(f1.getX === Fn.prototype.getX); // true

在IE浏览器中,原型模式也是同样的原理,但是IE浏览器怕你通过__proto__把公有的修改,禁止我们修改__proto__

批量设置共有属性

  1. 起别名
function Fn(){
    this.x = 100;
}
var pro = Fn.prototype;
pro.getX = function(){}
pro.getY = function(){}
  1. 重构原型对象的方式
function Fn(){
    this.x = 100;
}
Fn.prototype = {
    getX: function(){},
    getY: function(){}
}
var f = new Fn;
console.log(f.constructor)' // Object

只有浏览器天生给Fn.prototype开辟的堆内存里面才有constructor,而我们自己开辟的这个堆内存没有这个属性,
这样constructor指向就不再是Fn而是Object

为了和原来的保持一致,我们需要手动的增加constructor的指向

Fn.prototype = {
   constructor: Fn
}

会把之前已经存在于原型上的属性和方法给替换掉, 用这种方式修改内置类的话, 浏览器会给屏蔽掉

Array.prototype = {
    constructor: Array,
    unique: function(){}
}
console.dir(Array.prototype);

但是可以使用prototype属性,一个个修改内置的方法,如果方法名和原来内置的重复了, 会把内置的修改掉, 在内置类的原型上增加方法, 名命都需要加特殊的前缀

Array.prototype.sort = function(){
    console.log("lemon");
}
var ary = [1, 2, 2, 1, 2, 3, 4];
ary.sort();
console.log(ary);

常用的六种继承模式

for in 循坏在遍历的时候, 可以把自己私有的和在它所属原型上扩展的属性和方法都遍历到.

Object.prototype.aaa = function(){};
var obj = {name: 'lemon', age: 22};
for(let key in obj){
    console.log(key)
}

可以使用以下方法,进行判断处理

for(let key in obj){
    if(obj.propertyIsEnumerable(key)){
        console.log(key);
    }
}
for(let key in obj){
    if(obj.hasOwnProperty(key)){
        console.log(key);
    }
}

Object.create(proObj)

创建一个新的对象, 但是要把proObj作为这个对象的原型, 在IE6-IE8不兼容(ECMAScript5)

var obj = {
    getX: function(){}
}
var obj2 = Object.create(obj)
console.dir(obj2)
obj.getY = function(){}
console.dir(obj2)

自己实现一个create

var obj = {
    getX: function(){}
}
function object(o){
    function Fn(){}
    Fn.prototype = o;
    return new Fn();
}
var newObj = object(obj);

原型链继承

原型继承是JS中最常用的一种继承方式, 子类B想要继承父类A中的所有的属性和方法(私有+公有), 只需要让B.prototype = new A;
特点: 它是把父类中的私有+公有的都继承到了子类原型上(共有的)
核心: 原型继承并不是把父类中的属性和方法克隆一份一模一样的给B,而是让B和A之间增加了原型链的连接, 以后B的实例n想要A中的getX方法,需要一级一级的向上查找来使用

function A(){
    this.x = 100;
}
A.prototype.getX = function(){
    console.log(this.x)
}
function B(){
    this.y = 200;
}
B.prototype = new A

缺点: 不安全, 可以通过子类或子类的实例,更改父类原型链上的属性和方法, 对A的实例和子类造成影响

var b = new B
var a = new A
b.__proto__.__proto__.getX = 3000;
console.log(a.getX)
B.prototype.__proto__.getX = 2000;
console.log(a.getX)

call继承

借用构造函数, 伪造对象继承和经典继承
call:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.call(A, args1,args2);即A对象调用B对象的方法。

function A(){
    this.x = 100;
}
A.prototype.getX = function(){
    console.log(this.x);
}
function B(){
    A.call(this)
}
var b = new B;
console.log(b.x)

缺点:
父类在原型链中定义的函数不能被子类访问,也就是说所有的函数都必须写在构造函数内部,无法复用

冒充对象

把父类私有和公有的属性和方法,克隆一份一模一样的给子类私有的

function A(){
    this.x = 100;
}
A.prototype.getX = function(){
    console.log(this.x);
}
function B(){
    var temp = new A;
    for(var key in temp){
        this[key] = temp[key];
    }
}
var b = new B;
console.log(b.x)

混合模式继承

子私有 = 父私有, 子公有 = 父私有 + 父公有

function A(){
    this.x = 100;
}
A.prototype.getX = function(){
    console.log(this.x);
}
function B(){
    A.call(this)
}
B.prototype = new A;
B.prototype.constructor = B;
var b = new B;
console.log(b.x)

寄生组合式继承

子私有 = 父私有, 子公有 = 父公有

function A(){
    this.x = 100;
}
A.prototype.getX = function(){
    console.log(this.x);
}
function B(){
    A.call(this)
}
B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;
var b = new B;
console.log(b.x)

中间类继承法,不兼容

function avgFn(){
    arguments.__proto__ = Array.prototype;
    arguments.sort(function (a, b) {
        return a - b;
    })
    arguments.pop()
    arguments.shift()
    return eval(arguments.join("+")) / arguments.length;
}
avgFn(10, 20 ,30 ,10 ,30, 40, 40); // 26

标签:function,console,log,模式,JS,getX,原型,prototype,Fn
来源: https://www.cnblogs.com/xiaoxu-xmy/p/13644998.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有