在JavaScript中,new
关键字用于创建一个对象的实例。当使用new
关键字调用一个函数时,JavaScript会自动执行以下操作:
- 创建一个新的空对象。
- 将这个新对象的原型(
__proto__
属性)设置为构造函数的prototype
属性。 - 将构造函数的
this
关键字绑定到新创建的对象上。 - 执行构造函数中的代码,通常是初始化新对象的属性。
- 如果构造函数没有显式返回一个对象,则自动返回新创建的对象。
在您提供的代码中,MyTreeTableConstructr
函数被定义为一个构造函数,它返回一个MyTreeTable
对象。当使用new
关键字调用MyTreeTableConstructr
时,JavaScript会执行上述步骤,创建一个新的MyTreeTable
对象的实例。
在内存中,new
操作符会分配一块新的内存空间来存储新创建的对象。这个对象的属性和方法会被存储在这块内存空间中。同时,对象的原型(__proto__
属性)会被设置为构造函数的prototype
属性,这意味着对象可以访问构造函数原型上定义的属性和方法。
在指针方面,新创建的对象的__proto__
属性会指向构造函数的prototype
属性。这是通过JavaScript的原型继承机制实现的,它允许对象继承构造函数原型上的属性和方法。
总结来说,当使用new
关键字调用一个构造函数时,JavaScript会在内存中创建一个新的对象,将构造函数的this
绑定到这个新对象上,并执行构造函数中的代码来初始化对象的属性。同时,对象的原型会被设置为构造函数的prototype
属性,从而实现原型继承。
import { defineComponent } from 'vue';
import { h } from 'vue';import TreeTable from 'primevue/treetable';
import Column from 'primevue/column';//构造函数function MyTreeTableConstructr() {return MyTreeTable;
}const MyTreeTable = defineComponent({
// 定义合法的属性名列表validProperties: ['mytreeData', 'property2', 'property3'],name: 'MyTreeTable',components: {TreeTable,Column},// 接受外部的赋值non_TreetableData_object_param_list:[],setup() {// 定义数据const non_TreetableData_object_param_list=[{object_Name:'A+B+C+D',id_cases:'用例1',id_param:1,required:1,is_object:true,type:2,desc:'参数描述',children: [{required:1,is_object:false,id_param:2,id_parent:1,object_Name:'A',type:3,desc:'参数描述',rule:{id:1,min_length:1,// 最小长度max_length:65535,// 最大长度desc:'文本域类型规则描述',// 描述}},{required:1,is_object:false,id_param:3,id_parent:1,object_Name:'B',type:4,desc:'参数描述',rule:{id:1,// 业务编号type:1,// 种类:小数max:8,// 最大数值min:-8,// 最小数值precision:2,// 精度desc:'数值类型规则描述',// 描述}},{required:1,is_object:false,id_param:4,id_parent:1,object_Name:'C',type:2,desc:'参数描述',rule:{id:1,// 业务编号type:1,// 种类:小数date_type:1,// 日期格式类型time_type:1,// 时间格式类型max:8,// 最大日期min:-8,// 最小日期precision:2,// 精度desc:'日期类型规则描述',// 描述}},{required:1,is_object:false,id_param:5,id_parent:1,object_Name:'D',type:1,desc:'参数描述',rule:{id:1,default_length:1024,//默认值min_length:1,// 最小长度max_length:65535,// 最大长度special_type:1,// 特殊文本类型desc:'文本类型规则描述',// 描述}},{required:1,is_object:false,id_param:14,id_parent:1,object_Name:'E',type:5,desc:'参数描述',rule:{id:1,file_type:1,// 种类unit:1,// 单位max_length:65535,// 单个文件最大长度allow_type: [1,2,3],// 允许的类型desc:'文件类型规则描述',// 描述}},{required:1,is_object:false,id_param:15,id_parent:1,object_Name:'K',type:6,desc:'参数描述',rule:{id:1,name:'限选框名称',//名称limitedNumber:1,//限选类型:1单选 2多选type:1,// 类型:1文本 2数字desc:'限选类型规则描述',// 描述limitedOptionsList:[{name:'qq',desc: '限选值描述'},{name:'xx',desc: '限选值描述'},{name:'yy',desc: '限选值描述'},]}},{required:1,is_object:false,id_param:16,id_parent:1,object_Name:'H',type:7,desc:'参数描述',rule:{id:1,name:'限选框名称',//名称limitedNumber:1,//限选类型:1单选 2多选type:1,// 类型:1文本 2数字desc:'其他类型规则描述',// 描述}},]},];const transformData=(data)=> {const transform = (arr, parentKey = '') => {return arr.map((item, index) => {const newKey = parentKey? `${parentKey}-${index}` : `${index}`;const newItem = {key: newKey,data: {id_cases: item.id_cases,id_param: item.id_param,object_Name: item.object_Name,type: item.type,desc: item.desc,is_object : item.is_object,required : item.required,rule:item.rule,},children: item.children? transform(item.children, newKey) : []};return newItem;});};return transform(data);};const treeData = transformData(non_TreetableData_object_param_list);const displayNameBasedOnId=(typeId)=> {const typeMap = [{name: "文本", id: 1},{name: "日期", id: 2},{name: "文本域", id: 3},{name: "数值", id: 4},{name: "文件", id: 5},{name: "限选项", id: 6},{name: "其他", id: 7}];for (let i = 0; i < typeMap.length; i++) {if (typeMap[i].id === typeId) {return typeMap[i].name;}}return "未定义类型";};return () =>h(TreeTable, { value:treeData , tableStyle: 'min - width: 50rem' }, [h(Column, { field: 'object_Name', header: '分类名称', expander: true }),h(Column, { field: 'is_object', header: '分类类型' }),h(Column, { field: (item) => displayNameBasedOnId(item.type), header: '参数类型' }),h(Column, { field: 'required', header: '是否必须' }),h(Column, { field: 'desc', header: '描述' })]);}});
export default MyTreeTableConstructr;
import MyTreeTableConstructr from '@/service/prd/test/mytreetable.js';
const MyTreeTable = new MyTreeTableConstructr();
-
为什么可以直接
new
-
构造函数的本质
- 在JavaScript中,函数可以被用作构造函数。虽然
MyTreeTableConstructr
函数看起来比较简单,但只要它是一个函数,就可以使用new
关键字来创建一个新的对象实例。这里的MyTreeTableConstructr
函数被视为构造函数,它返回一个MyTreeTable
对象(假设MyTreeTable
在函数内部或者其他地方已经被正确定义)。
- 在JavaScript中,函数可以被用作构造函数。虽然
-
模块导入与函数可用性
- 通过
export default MyTreeTableConstructr
将函数导出,再使用import MyTreeTableConstructr from '@/service/prd/test/mytreetable.js';
将函数导入到另一个模块。导入后的函数在当前模块的作用域内是可用的,并且可以按照JavaScript的规则使用,包括使用new
关键字来创建实例。
- 通过
-
-
new
操作时内存和指针的变化-
内存方面
-
创建新对象:
- 当执行
new MyTreeTableConstructr()
时,JavaScript首先会在内存中开辟一块新的空间来存储即将创建的新对象。这个新对象最初是一个空对象,它有自己独立的内存地址。
- 当执行
-
存储对象属性:
- 如果在
MyTreeTableConstructr
函数内部有对this
对象(也就是新创建的对象)的属性赋值操作(虽然在当前代码中未显示,但一般构造函数会有这样的操作),那么这些属性会被存储在新对象的内存空间中。例如,如果函数内部有this.property = 'value';
这样的操作,property
的值value
就会被存储在新对象的内存空间里。
- 如果在
-
-
指针方面
-
设置原型指针:
- 新创建的对象有一个特殊的内部属性
__proto__
(在现代JavaScript中,更推荐使用Object.getPrototypeOf()
来获取原型,但__proto__
仍然可以用于理解概念)。当使用new
操作符时,这个新对象的__proto__
指针会被设置为指向MyTreeTableConstructr
函数的prototype
属性。这意味着新对象可以继承MyTreeTableConstructr.prototype
上的属性和方法。例如,如果MyTreeTableConstructr.prototype.someMethod = function(){};
,那么新创建的MyTreeTable
对象就可以调用someMethod
方法,因为通过__proto__
指针建立了这种继承关系。
- 新创建的对象有一个特殊的内部属性
-
函数返回对象与新创建对象的关系:
- 由于
MyTreeTableConstructr
函数返回MyTreeTable
,如果MyTreeTable
是一个对象(这里假设它是),那么最终const MyTreeTable = new MyTreeTableConstructr();
中的MyTreeTable
会指向这个返回的对象。如果MyTreeTable
不是一个对象(例如是一个基本类型的值),那么根据new
操作符的规则,如果构造函数没有显式返回一个对象,new
操作符会返回新创建的对象(也就是this
对象,在这个例子中是最初开辟内存空间创建的那个新对象)。
- 由于
-
-