当前位置:网站首页>js创建对象,构造函数,this,原型,继承
js创建对象,构造函数,this,原型,继承
2022-08-11 11:51:00 【-加油】
js创建对象
1、使用构造函数
使用函数声明式创建函数对象
(各实例间互不影响,是两个不同的实例)
function Fun(){
this.name = ['林北星','张万森','展宇'];
this.age = ['17','17','19'];
this.fun = function(){
console.log('这是对象的方法');
}
}
console.log(Fun);
var s1 = new Fun();//创建实例对象
var s2 = new Fun()
// 这两个是不同的实例 是不同的Fun对象
console.log(s1);
console.log(s2);
s1.name.push('hhhh');//修改s1不会影响s2
console.log(s1);
console.log(s2);
s1.fun();//使用属性方法
或者
使用函数表达式赋值式创建函数对象
同样(各实例间互不影响,是两个不同的实例)
let Fun=function(){
this.name = ['林北星','张万森','展宇'],
this.age = ['17','17','19'],
this.fun = function(){
console.log('这是对象的方法');
}
}
console.log(Fun);
var s1 = new Fun();//创建实例对象
var s2 = new Fun()
// 这两个是不同的实例 是不同的Fun对象
console.log(s1);
console.log(s2);
s1.name.push('hhhh');//修改s1不会影响s2
console.log(s1);
console.log(s2);
s1.fun();//使用属性方法
或者
(各实例间影响,因为传的同一个数组——引用类型)
引用传递
function Fun(name,age){
this.name = name;
this.age = age;
this.fun = function(){
console.log('这是对象的方法');
}
}
let names = ['林北星','张万森','展宇'];
let ages = ['17','17','19'];
// 数组是对象,数组names,ages都是引用传递的
var s1 = new Fun(names,ages);//创建实例对象
var s2 = new Fun(names,ages);//创建实例对象
console.log(s1);
console.log(s2);
console.log(s1.name);// 数组 [ '林北星', '张万森', '展宇' ]
console.log(s1.name===s2.name);// true
console.log(s1.age===s2.age);// true
s1.name.push('hhhh');//修改s1同时修改了s2
console.log(s1);
console.log(s2);
s1.fun();//使用属性方法
或者
不影响 传的不是同一个,是两个不同的实例。
function Fun(name,age){
this.name = name;
this.age = age;
this.fun = function(){
console.log('这是对象的方法');
}
}
let name1 = ['林北星','张万森','展宇'];
let age1 = ['17','17','19'];
let name2 = ['庄文杰','罗坚','大智'];
let age2 = ['17','17','19'];
var s1 = new Fun(name1,age1);//创建实例对象
var s2 = new Fun(name2,age2);//创建实例对象
console.log(s1);
console.log(s2);
s1.name.push('hhhh');//修改s1不会修改s2
console.log(s1);
console.log(s2);
s1.fun();//使用属性方法
2、Object
let s = new Object();
s.name = ['林北星','张万森','展宇'];
s.age = ['17','17','19'];
s.fun = function(){
console.log('这是对象的方法');
}
console.log(s);
s.fun();
或者:
let s = new Object({
name:['林北星','张万森','展宇'],
age:['17','17','19'],
fun(){
console.log('这是对象的方法');
}
// 也可以这么写:
// fun:function(){
// console.log('这是对象的方法');
// }
})
console.log(s);
s.fun();
或者
let s = {
name:['林北星','张万森','展宇'],
age:['17','17','19'],
fun(){
console.log('这是对象的方法');
}
// 也可以这么写:
// fun:function(){
// console.log('这是对象的方法');
// }
}
console.log(s);
s.fun();
或者
Object.create
两个实例相互影响
let s1 = {
name:['林北星','张万森','展宇'],
age:['17','17','19'],
fun(){
console.log('这是对象的方法');
}
// 也可以这么写:
// fun:function(){
// console.log('这是对象的方法');
// }
}
console.log(s1);
let s2 = Object.create(s1)
console.log(s2);
s2.name.push('hhhh');//修改s1 也会影响s2
console.log(s1);
console.log(s2);
s1.fun();
3.原型
构造函数与实例
function Fun(){
this.name = ['林北星','张万森','展宇'];//私有 不共享
this.age = ['17','17','19'];
this.fun = function(){
console.log('这是对象的方法');
}
}
let s = new Fun();
//实例与构造函数
console.log(s.__proto__==Fun.prototype);//true
构造函数与原型对象
Fun.prototype .constructor===Fun
每个函数都有prototype属性,它的结构:
Fun.prototype = {
constructor: Fun,
......其他原型属性和方法
}
原型对象作用:为每个实例对象存储共享的方法和属性。
所有的实例共享同一个原型对象。
实例有很多份,实例属性和方法是独立的。
在构造函数中,为属性的私有性,方法的复用共享性,一般将属性封装在构造函数中,将方法定义在原型对象上。
4.继承
原型链继承
parent一般将属性封装在构造函数中,将方法定义在原型对象上。
new Parent
优点:共享原型对象上的方法,方法定义在父类原型上,复用父类构造函数方法,如say方法。
缺点:
子实例会共享父类构造函数的引用属性。比如下例子的arr属性。
无法实现多继承。
不能向父类传参。
function Parent(name,age){
//属性封装在构造函数中
this.name = name;
this.age = age;
this.arr = [1];
}
//方法定义在原型对象上
Parent.prototype.say = function(){
console.log('hhhhhhh');
}
function Child(like){
this.like = like;
}
//原型链继承
Child.prototype = new Parent('庄文杰','19');//此时Child.prototype.constructor == Parent
Child.prototype.constructor = Child;
let s1 = new Child('sing');//这个传参,不能传到父类构造函数
let s2 = new Child('dance');//这个传参,不能传到父类构造函数
s1.say();//输出hhhhhhh
s2.say();//输出hhhhhhh
console.log(s1.say===s2.say);//true 复用,是共享的
console.log(s1.name);
console.log(s2.name);
console.log(s1.arr);
console.log(s2.arr);
s1.arr.push(2);//修改s1的arr,s2也会影响
s1.name = '罗队';//修改s1的name,不会影响s2
console.log(s1.arr);
console.log(s2.arr);
console.log(s1.name);
console.log(s2.name);
用构造函数继承
使用call 改变this指向
new Child
优:可向父类构造函数传参,不共享引用属性。
缺:方法不能复用,独立的。
不能继承父类原型上的方法。
function Parent(name){
this.name = name;
this.arr = [1];
this.say = function(){
console.log('hhhhhhhhhh');
}
}
Parent.prototype.fun = function(){
console.log('pppppp');
}
function Child(name,like){
Parent.call(this,name);//把this指向Child,拷贝了父的实例属性和方法
this.like = like;
}
let s1 = new Child('庄文杰','sing');//向父类传参
let s2 = new Child('罗队','dance');
console.log(s1.name);
console.log(s2.name);
console.log(s1.arr);
console.log(s2.arr);
s1.arr.push(2);//修改s1的arr 不会影响到s2
console.log(s1.arr);
console.log(s2.arr);
console.log(s1.say===s2.say);//false 独立的
s1.fun();//报错 fun is not a function
s2.fun();//不能继承父类原型上的方法
组合继承
原型链继承+构造函数继承
function Parent(name){
//属性封装在构造函数中
this.name = name;
this.arr = [1];
}
//方法定义在原型对象上
Parent.prototype.say = function(){
console.log('hhhhhhh');
}
function Child(name,like){
Parent.call(this,name)
this.like = like;
}
Child.prototype = new Parent();//此时Child.prototype.constructor == Parent
Child.prototype.constructor = Child;
let s1 = new Child('庄文杰','sing');//这个传参,不能传到父类构造函数
let s2 = new Child('罗队','dance');//这个传参,不能传到父类构造函数
s1.say();//输出hhhhhhh
s2.say();//输出hhhhhhh
console.log(s1.say===s2.say);//true 复用,是共享的
console.log(s1.name);
console.log(s2.name);
console.log(s1.arr);
console.log(s2.arr);
s1.arr.push(2);//修改s1的arr,不会影响s2 没共享
s1.name = '大智';//修改s1的name,不会影响s2
console.log(s1.arr);
console.log(s2.arr);
console.log(s1.name);
console.log(s2.name);
由于调用两次父类构造方法, Parent.call(this,name)和new Parent(),会存在一份多余的父类实例属性。
优化:
改成
原型式继承+构造函数
Child.prototype = Parent.prototype;
还是有缺点:当修复子类构造函数的指向后:
Child.prototype.constructor = Child;
父类实例的构造函数指向也会跟着变。
再优化:
改成
寄生组合继承:
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
ES6 extends继承
class Parent{
constructor(){
this.age = 18;
}
}
//子Child 继承父 Parent super 必须在子的this.xxx = xxx前面
//子没有自己的this,它是继承父的this,所以需要先super获得this
class Child extends Parent{
constructor(){
// this.name = '庄文杰'; 会报错 super()必须在前面
super();//因为Child没有this指向,这句必须要有
this.name = '庄文杰';
}
}
let obj = new Child();
// console.log(obj.age);//18
console.log(obj.name);//庄文杰
继承super含参数
class Parent{
constructor(age,sex){
this.age = age;
this.sex = sex
this.dd = '我是爹地'
this.tv = '重生之门'
}
say(){
console.log('扮演'+this.boy);
}
hi(){
console.log('这部剧叫'+this.tv);
}
father(){
return this.dd
}
}
class Child extends Parent{
constructor(name,_age,_sex){
super(_age,_sex);
this.name = name;
this.boy = '庄文杰';
this.dd = '庄耀柏'
// this.tv = '重生' 有它则是它
}
son(){
//注意father中的this
console.log(super.father()+'的儿砸');
}
}
let obj = new Child('王俊凯','18','男');
console.log(obj.age);//18
console.log(obj.name);//王俊凯
obj.say();//扮演庄文杰
obj.hi();//这部剧叫重生之门 注意这里的tv
obj.son();//庄耀柏的儿砸 注意这里的dd
super:
//this指向函数所在的当前 对象
//super 指向当前对象的 原型对象
var obj1 = {
fun1(){
console.log('obj1的fun1');
}
}
var obj2 = {
fun2(){
//使用super前提:将obj2的原型加到obj1上
super.fun1();//实际上是调用obj2.prototype.fun1()
}
}
//将obj2的原型加到obj1上
Object.setPrototypeOf(obj2,obj1)
obj2.fun2();//obj1的fun1
//this指向函数所在的当前 对象
//super 指向当前对象的 原型对象
var obj1 = {
name:'obj1',
fun1(){
return this.name
}
}
var obj2 = {
name:'obj2',
fun2(){
//使用super前提:将obj2的原型加到obj1上
console.log(super.name);//obj1
console.log(this.name);//obj2
return super.fun1()
}
}
//将obj2的原型加到obj1上
Object.setPrototypeOf(obj2,obj1)
//super 虽然指向原型对象的fun1方法,但是this指向还是绑定当前obj2对象
console.log(obj2.fun2());//obj2
边栏推荐
猜你喜欢
seata相关图形,dljd,cat
重要消息丨.NET Core 3.1 将于今年12月13日结束支持
为什么最好的光刻机来自荷兰,而不是芯片大国美国?
Through the thermal lens focus on different types of gaussian model
edusoho兑换码功能二次开发
ESI VA One 2021软件安装包和安装教程
在华门店数超星巴克,瑞幸咖啡完成“逆袭”?
EXCLUSIVE INTERVIEW | INTELLIGENCE IS SPONTANED, NOT PLANNED: Evolution Fan, Former OpenAI Research Manager and UBC Associate Professor Jeff Clune
Five minutes to teach you intranet penetration
MySQL之JDBC编程增删改查
随机推荐
公共经济学(开卷)期末复习题
PlutoSDR学习指南【1】环境搭建+资料分享
03-JS条件分支及循环
阿里云慢下来了?
TX12 + ExpressLRS RC configuration and control link problem summary 915 MHZ
面试官:Redis Zset的实现为什么用跳表,而不用平衡树?
Flutter经验整理
困扰所有SAP顾问多年的问题终于解决了
从零开始Blazor Server(10)--编辑角色
Tool_RE_IDA基础字符串修改
【五一特刊】FPGA零基础学习:VGA协议驱动设计
The old saying: The interview must ask "Three handshakes, four waves", so you can't forget it
2022 OceanBase 年度发布会:发布四大策略,迈入4.0时代
三面蚂蚁金服,分享面试经历总结(已拿offer)
Visual Studio: Arm64EC官方支持来了
在华门店数超星巴克,瑞幸咖啡完成“逆袭”?
d,cast转换aa为右值
Go编译原理系列10(逃逸分析)
【ManageEngine】网络带宽管理工具
EXCLUSIVE INTERVIEW | INTELLIGENCE IS SPONTANED, NOT PLANNED: Evolution Fan, Former OpenAI Research Manager and UBC Associate Professor Jeff Clune