js中的原型

296 阅读3分钟

什么是原型?

打个比方:你想去旅游,但是你没钱,你父母有啊,你可以用你父母的钱去旅游!这个父母就是原型!!

贴段代码:

let arr=["对象在哪"]
console.log(arr.concat("对象在这"))  //输出都知道就不看了

image.png

为什么arr可以使用concat方法,因为父亲(原型)有啊。父亲是不是还有父亲,所有原型上还有原型,原型上还有院校就形成了原型链。

对象也可以没有原型,这就要用上Object.create()方法创建,new也可以。两者有什么区别呢?

通过Object.create(null) 创建一个干净的对象,也就是没有原型,而 new Object() 创建的对象是 Object的实例,原型永远指向Object.prototype

原型方法和对象方法的优先级:

//自定义一个对象方法
let jx={
show(){
console.log("你真好看")
}
}
//往原型对象上添加一个方法
jx.__proto__.show=function(){
console.log("好好生活")
}
jx.show()  //你真好看

结论:对象优先级大于原型优先级,好比旅游,你有钱(这个方法)就不会去找父亲(原型)要钱(上的方法)

函数:函数也是对象。函数有几个原型(prototype和__proto__)

  1. prototype 是函数(function) 的一个属性, 它指向函数的原型.
  2. proto  是对象的内部属性, 它指向构造器的原型, 对象依赖它进行原型链查询. 由上, prototype 只有函数才有, 其他(非函数)对象不具有该属性. 而  proto  是对象的内部属性, 任何对象都拥有该属性.
        function user(){}
        user.prototype.show=function(){
            console.log('11');
        }
        console.dir(user);
        let h=new user()
        h.show()
        console.log(user.prototype==h.__proto__)//true

user既是function 的实例对象,所以有__proto__,但只有函数才有prototype,所以user即是函数又是实例对象

function , Object , boolea,String,REGEXP(正则)的实例对象的__proto__和他们的构造函数的prototype一样

let arr= []  //new Array
console.log(arr.__proto__==Array.prototype) //true

let str ="" //new String
console.log(str.__proto__==String.prototype) //true

let bool = true
console.log(bool.__proto__==Boolean.prototype) //true

let reg=/a/i  //new RegExp
console.log(reg.__proto__==RegExp.prototype) //true

let obj={}  //new Object
console.log(obj.__proto__==Object.prototype) //true
                                                                                                                                                                                                                                                              

我们可以自己自定义对象的原型设置:setPrototypeOf()。getPrototypeOf()可以查看原型上的属性和父亲

let jx={name:"jx"}
let xj={}
let parent = {name:"parent",
show(){
console.log("我是parent的方法")                                                                                                                                                                                                                                                             
}
}
Object.setPrototypeOf(jx,parent)//第一个为实例对象名,第二个为父亲,之前说过可以使用原型上的方法也就是父亲的方法,也就是一个继承的过程
jx.show(); //我是parent的方法
//console.log(jx.__proto__ == Object.prototype) //true
Object.getPrototypeOf(jx)

1.setPrototypeOf方法:给实例对象设置了一个名字为parent的父亲 image.png

2.getPrototypeOf方法:查看jx的原型,看到了他的父亲为parent

image.png

原型链:举个例子把:

let a={name:'a'}
let b={name:'b',
show(){
console.log('我是b中的方法'+this.name)
},
hello(){
console.log('我是b,你好呀')
}
}
let c={name:'c'}
Object.setPrototpeOf(a,b)  //把a的父亲设置为b,也就是在b的原型链上a 的父亲变成了b,可以使用b的所有属性和方法(前提自己没有的情况下)
Object.setPrototpeOf(c,b)
a.show() //我是b中的方法 a
c.show() //我是b中的方法 c

所以当子集们都有一个公用的方法时,可以把这个方法写到父亲身上,子集上就不需要去一个个添加这个方法。比如:一个造车厂,车长,车宽是不是都固定的,车场就是父亲,每辆车就是儿子。儿子们都要这个方法,就写到父亲身上。