全部
常见问题
产品动态
精选推荐

一文彻底搞懂引用类型

管理 管理 编辑 删除

引用类型的值(对象)是引用类型的一个实例。引用类型有时也称对象定义,因为它们描述的是一类对象所具有的属性和方法。

对象是某个特定引用类型的实例,新对象是使用new操作符后跟一个构造函数来创建的,构造函数本身就是一个函数,只不过该函数是出于创建新对象的目的而定义的。

ver dada = new Object();

JavaScript对象划分为:

引用类型,基本包装类型,内置对象

JavaScript引用类型分:Object类型,Array类型,RegExp类型,Date类型,Function类型。

基本包装类型,Boolean类型,Number类型,String类型。

Object类型

Object类型是JavaScript中常见的一种类型,使用new操作符

var dada = new Object();
dada.name = "dada";
dada.age = 12;

使用对象字面量表示法:

var dada = {
 name: 'dada',
 age: 12,
}

访问对象的属性

console.log(dada.name);

console.log(dada['name']);
var dadaname = "dada";
console.log(dada[dadaname]);

注意,除非是必须非要使用变量来访问属性,否则不建议使用,还是建议使用点方法来表示。

new运算符的作用就是创建一个对象的实例,这个对象可以是用户自定义,也可以是带有构造函数的一些系统自带的对象。

创建Object类型有两种方法:

第一,使用new运算符创建Object,第二,使用对象字面量方式创建Object,使用最多。

判断js对象是否拥有这个属性,第一种,使用in判断对象的所有属性,包含对象实例以及其原型的属性;第二种,使用

Object.hasOwnProperty(proName);判断的是对象的实例是否具有某个属性。

引用类型通常叫做类,即是,遇到引用值,可以理解为对象。

对象是由 new 运算符加上要实例化的对象的名字创建的

var o = new Object();

Object对象具有的属性

constructor对创建对象的函数的引用(指针),对于Object对象,该指针指向原始的Object()函数。

检测数组

instanceof

Array.isArray(value)

Object.prototype.toString.call(obj)

转换方法

toString() 返回字符串

valueOf() 返回数组本身

toLocaleString()

join()

var dada = ['da1','da2'];

dada.toString()
"da1,da2"

dada.valueOf()
['da1','da2']

添加移除

push()数组末尾接收任意数量,并返回修改后的数组的长度。

pop()数组末尾移除最后一项,减少length值,返回移除的项

shift()移除数组第一项,并返回该项,数组长度减一

unshift()数组前面添加任意项并返回新的数组的长度

重排序

reverse() 反转

sort()排序

var arr = [1,3,7,9,4,5]

var arr2 = arr.sort(function(a,b) {
 // 从小到大的排序
 return a-b
 // 从大到小的排序
 return b-a
})

console.log(arr2);

操作方法,concat()创建当前数组的一个副本,如果有参数则添加这个副本的末尾,如果没有参数就返回当前数组的副本。

slice(start,end)接收一个或两个参数,但不返回结束位置的项,不会影响原数组;splice(起始位置,删除的项数量,要插入的项),删除,替换,插入。

dada.splice(1, 0, 'da1','da2');
// dada从1位置插入两项

dada.splice(1,1, 'da1','da2');
// 为在1位置删除1项,插入两项

indexOf()从数组开头向后查找

lastIndexOf()从数组的末尾开始向前查找

返回的是查找项在数组中的位置,如果没有找到就返回-1

基本类型值和引用类型值,基本类型值是简单的数据,而引用类型是指由多个值构成的对象。

基本类型,undefined,null,boolean,number,string

引用类型,Object,Array等

从一个变量向另一个变量复制引用类型的值时,同样也会将存储在变量对象中的值复制一份到新变量分配的空间中。不同的是,这个值的副本实际上是一个指针,这个指针指向存储在堆中的一个对象,复制后的结果是,两个变量实际上将引用同一个对象,两个变量对象指向堆内存中同一个Object对象,所以当改变其中一个变量,就会影响另一个变量。

var dada = new Object();


var dashu = dada;


dada.name='da1';


console.log(dashu.name);
// da1

数值的传递,函数的参数

在JavaScript中所有函数的参数都是使用值传递的,就是把函数外的值复制传递给函数内部的参数,就好像从一个变量赋值到另一个变量一样

基本类型值的传递如同基类型变量的复制效果一样,引用类型的值传递,就如同引用类型变量的复制一样的效果。

在向参数传递基本类型值时,被传递的值会复制给一个局部变量,在向参数传递引用类型的值时,会把这个值在内存中的地址复制给这个局部变量。

基本类型

function add(num) {
    num += 1;
    return num;
}


var da1 = 12;


var result = add(da1);


console.log(da1);


console.log(result);

引用类型

function setName(obj) {
    obj.name = 'dada';
}


var person = new Object();


setName(person);


console.log(person.name);


dada

typeof检测基本类型

typeof中 var da; // 检测为undefined

typeof中 var da = null; // 检测为object

typeof中 var da = new Object(); // 检测为object

instanceof检测引用类型的值

如果不是检测的不是引用类型的值,而是基本类型的值,则返回false

如果是引用类型的值,返回为true

var d = new Number(11);


console.log(d instanceof Number);


true

Object.prototype.toString表示返回一个表示该对象的字符串

Object.prototype.toString.call(null);


"[object Null]"


Object.prototype.toString.call(1111);


"[object Number]"


Object.prototype.toString.call('string');


"[object String]"

总结Object类型,大部分引用类型值都是Object类型的实例,创建Object实例的方式有两种,一种是使用new操作符后跟Object构造函数,一种是使用对象字面量表示法。

array类型,Date类型,RegExp类型,Function类型,基本包装类型是什么呢?

我相信你在学习时一定见到过Array类型,也是最常见的,数组的每一项可以存储任何类型的数据,数组的大小是可以动态变动的,数组的长度越大就可以存储更多的数据。

那么第一问,数组是怎么创建的呢?

数组有哪些自带的属性,如何检查是否为一个数组,数组元素的增删改等,数组与字符串的相互转化,数据的一些方法,如,截取,合并,排序,查找数组元素的元素,如何遍历数组,进行迭代等。

数组的创建,同样数组也有两种基本的创建方式,一种是使用array构造函数,和创建对象一样new Object()方法。看看使用Array构造函数的语句代码:

var da = new Array();


new Array(); // 创建一个数组


new Array([size]); // 创建一个数组并指定长度


new Array(element0, element1, ..., elementn);  
// 创建一个数组并赋值

采用字面量的方法

var da = []; // 创建一个空数组


var da1 = [1,2,3]; // 创建一个有三个元素的数组

var da1 = [1,2,3];


console.log(da1 instanceof Array);
VM272:1 true

var dada = [1,2,3];
undefined


console.log(Array.isArray(dada));
VM422:1 true

检查是否是数组的两种方法:

一种使用instanceof,一种使用Array.isArray()方法。

constructor 
// 返回创建数组对象的原型函数


length
// 返回数组的长度


prototype
// 可以增加数组的原型方法和函数


可以看出一个数组中方法:

_proto_
concat
constructor
copyWithin
entries
every
fill
filter


find
findIndex
flat
flatMap


forEach
includes
indexOf
join
keys


lastIndexOf
length


map
pop
push
reduce
reduceRight


reverse
shift
slice
some
sort


splice
toLocaleString
toString
unshift

数组的length属性,返回数组的长度。

var array = new Array();
undefined
console.log(array.constructor);
VM576:1 ƒ Array() { [native code] }
undefined
console.log(array.constructor === Array);
VM615:1 true
undefined

constructor属性返回对创建此对象的数组函数的引用,即是返回对象相对应的构造函数。

array.push(元素1,元素2,...)将一个或多个元素添加到数组的末尾,并返回新数组的长度。

array.unshift(元素1,元素2,...)将一个或多个元素添加到数组的开头,并返回新数组的长度。

array.pop()从数组中删除最后一个元素,并返回最后一个元素的值。

原始数组的最后一个元素被删除。

array.shift()删除数组的第一个元素,并返回第一个元素。

原始数组的第一个元素被删除。

array.splice(start 第一个参数为指定开始修改的位置,如果超出了数组的长度就从末尾开始添加内容,如果为负值,就从数组末尾开始的第几位,从1开始计数, deleteCount第二个参数为,要删除的元素的个数,是从start位置开始要删除的元素个数,为0时表示不删除元素,其后的参数为要加入的元素,从start位置开始,添加的元素。

数组转为字符串

array.join('')

所有对象都具有toLocaleString(),toString(),valueOf()方法

var da = [1,23,4];
undefined
console.log(da.toString());
VM727:1 1,23,4
undefined
console.log(da.valueOf());
VM813:1 (3) [1, 23, 4]
undefined
console.log(da.toLocaleString());
VM861:1 
undefined

toString()方法(toLocaleStirng方法),返回这个数组中每个值的字符串形式,拼接而成的一个以逗号分隔的字符串,valueOf()方法,返回的是数组本身。

当有一个值为null或者是undefined时,在join()方法,toStirng()方法和valueOf()方法,toLocaleString()方法的返回则都是以空字符串表示。

字符串变化为数组

string.split(第一个参数为字符串或者是正则表达式,从该参数指定的地方对字符串进行分割,第二个参数为指定返回的数组的最大长度)用于把一个字符串分割成字符串数组

数组的截取与合并

array.slice(start,end)方法,从数组中返回start下标开始,直到end下标结束(不包含),该方法不会改变原始数组,只会返回一个新的子数组。

var arr = [2,23,3,23];
undefined
array.slice(-1);
[]
console.log(arr);
VM1019:1 (4) [2, 23, 3, 23]
undefined
arr.slice(1,3)
(2) [23, 3]
console.log(arr);
VM1131:1 (4) [2, 23, 3, 23]
undefined

可以看出这个方法不会修改原始数组,只是会返回一个新的子数组,如果想要删除数组中的元素,可以使用array.splice()。

数组的合并

array.concat()方法

sort()方法用于对数组的元素进行排序,并返回原数组。

不带参数,按照字符串UniCode码的顺序进行排序。

const array = ['a', 'd', 'c', 'b'];
array.sort();  //['a', 'b', 'c', 'd']

按照数值大小进行排序-升序

array.sort((a,b) => {
 return a-b;
 // 从小到大排序
});

按照数值大小进行排序-降序

array.sort((a,b)=>{
 return b-a;
 // 从大到小排序
});

array.reverse()方法

reverse() 方法将数组中元素的位置颠倒,第一个数组元素成为最后一个数组元素,最后一个数组元素成为第一个。

数组的sort()和reverse()方法都对原数组进行了修改,返回值是经过排序之后的数组。

find(callback[, thisArg])方法,用于找出第一个符合条件的数组元素。

[1, 3, -5, 20].find((n) => n < 0)
// -5

findIndex(callback[, thisArg])返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1。

[1, 3, 13, 25].findIndex(function(value, index, arr) {
  return value > 9;
}) // 2
function f(value){
  return value > this.age;
}
let person = {name: 'dada', age: 20};
[1, 12, 25, 5].find(f, person);    // 25

includes(第一个参数为要查找的元素,第二个参数为开始查找的索引位置)方法,返回一个布尔值,表示是否存在给定值在该数组中。

array.filter()方法,array.every()方法检测数组中的每个元素是否通过测试的,如果测试通过为true。

arr.some()判断数组汇总是否包含可以通过测试的元素怒,和every不同的是,这里只要某一个元素通过测试,即返回true。

[2, 3, 15, 1, 4].some(item => item > 6);
// true
let a = [1, 2, 3, 4, 5];


let b = [];
a.forEach((item) => {
    b.push(item + 1);
});


console.log(b); // [2,3,4,5,6]

keys()是对键名的遍历、values()对键值的遍历、entries()是对键值对的遍历。

for(let item of ['a','b'].keys()){
    consloe.log(item);
    //0
    //1
}


for(let item of ['a','b'].values()){
    consloe.log(item);
    //'a'
    //'b'
}


let arr = [0,1];
for(let item of arr.entries()){
    console.log(item);  
    //  [0, 0]
    //  [1, 1]
}
const total = [0, 1, 2, 3].reduce((a, b) => {
  return a + b;
}, 0);
// total is 6
const da = [[0, 1], [2, 3], [4, 5]].reduce((a, b) => {
  return a.concat(b);
}, []);
// da is [0, 1, 2, 3, 4, 5]

Array.from()方法可以用来将json数组格式转换为数组

let da = {
    '0': 'a',
    '1': 'b',
    '2': 'c',
    length: 3
};


let arr = Array.from(da); // ['a', 'b', 'c']

Array.of()方法可以将一组值转换为数组

let da = Array.of(1,2,3,4);
console.log(da);//[1,2,3,4]
console.log(...[1, 2, 3])
// 1 2 3


console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5

栈方法,队列方法

数组的表示像栈一样,栈是一种后进先出的数据结构。

栈中项的插入(叫做推入)和移除(叫做弹出),只发生在一个位置——栈的顶部。

push()方法可以接收任意数量的参数,在数组的末尾逐个添加,并返回修改后数组的长度,pop()方法可以从数组末尾移除最后一项,返回移除的项。

队列方法

队列数据结构的访问方法是先进先出,队列在列表末端添加项,从列表的前端移除项。

every()方法,传入的函数必须对每一项返回true,才会返回true,否则它就返回false,some()方法则是只要传入的函数对数组中的某项返回true,就会返回true。

Object对象具有的属性

constructor

对创建对象的函数的引用(指针),对于Object对象,该指针指向原始的Object()函数。

Prototype

对该对象的对象原型 的引用,对于所有的对象,它默认返回Object对象的一个实例。

方法:

hasOwnProperty(property)

判断对象是否有某个特定的属性,必须要字符串指定该属性

IsPrototypeOf(object)

判断该对象是否为另一个对象的原型

PropertyIsEnumerable

判断给定的属性是否可以用for...in语句进行枚举

toString()返回对象的原始字符串表示。

valuOf()方法返回最合适该对象的原始值。

reduce()方法从数组的第一项开始,逐个遍历到最后。

reduceRight()方法从数组的最后一个项开始,向前遍历到第一项。

JavaScript引用类型中的Date对象

Date 类型使用自 UTC(Coordinated Universal Time,国际协调时间)1970 年 1 月 1 日午夜(零时)开始经过的毫秒数来保存日期。

创建Date对象,使用new 操作符和Date构造函数:

var date = new Date();


var date = new Date("1178/08/06 04:20:00");
var date = new Date(154656847478617);

静态方法,Date.now()方法返回当前时间距离时间零点,1970年1月1日00:00:00UTC的毫秒数,相当于Unix时间戳乘以1000。

getTime()方法

返回实例距离1970年1月1日00:00:00的毫秒数,等同于valueOf方法

Date类型使用UTC国际协调时间1970年1月1日午夜(零时)开始经过的毫秒数来保存日期。如果调用Date构造函数而不传递参数,则新创建的对象获取的是当前的日期和时间。

如果想要特定的日期和时间创建日期对象,传入参数。

// 提供了两个方法
Date.parse()
Date.UTC()

Date.parse()方法接收一个表示日期的字符串参数

var newDate = new Date(Date.parse('May 23, 2010'));

Date.UTC()方法返回表示日期的毫秒数。

getFullYear()  
返回四位的年份 

getMonth()  
返回月份(0 ~ 11,0表示1月,11表示12月) 

getDay()  
返回星期几,星期日为0,星期一为1,以此类推 

getDate()  
返回实例对象对应每个月的几号(从1开始) 

getHours()  
返回小时数 (0 ~ 23) 

getMinutes() 
 返回分钟数 (0 ~ 59) 

getSeconds()  
返回秒数 (0 ~ 59) 

getMilliseconds()  
返回毫秒数 (0 ~ 999)

setTime(milliseconds)  
设置毫秒时间戳 

setYear(year)  
设置距离1900年的年数 

setFullYear(year [, month, date])  
设置四位年份 

setMonth(month [, date])  
设置月份(0-11) 

setDate(date)  
设置实例对象对应的每个月的几号(1-31),返回改变后毫秒时间戳 

setHours(hour [, min, sec, ms])  
设置小时(0-23) 

setMinutes(min [, sec, ms])  
设置分钟(0-59) 

setSeconds(sec [, ms])  
设置秒(0-59) 

setMilliseconds()  
设置毫秒(0-999)
toDateString()

显示格式星期几,月,日,年

toTimeString()
显示时,分,秒和时区

toLocalDateString()
显示星期几,月,日,和年

toLocaleTimeString()
显示实现的格式显示时,分,秒

toUTCString()
显示完整的UTC日期

RegExp类型

ECMAScript 通过 RegExp 类型来支持正则表达式。

var expression = / pattern / flags ; 


// 模式(pattern)部分可以是任何简单或复杂的正则表达式


// 标志(flags)用以标明正则表达式的行为

g表示全局模式,即是模式将被应用于所有字符串

i表示不区分大小写模式

m表示多行模式

RegExp 构造函数接收两个参数:

一个是要匹配的字符串模式,一个是可选的标志字符串。

RegExp实例方法

exec()方法,用于检索字符串的正则表达式的匹配。

string,检索的字符串,返回一个数组,没有则返回null

/\d{2,4}/         //匹配2~4个数字
/\w{3}\d?/        //精确匹配三个单词和一个可选的数字

函数,函数其实是对象,每个函数都是Function类型的实例。

韩式是定义一次就可以调用或者是执行任意多次的一段代码,通过函数可以封装很多代码块,而且可以在任何地方,任何时候调用,函数本身没有运行功能,只有调用才能运行。

函数实际上是对象,每个函数都是Function类型的实例

函数名是指向函数对象的指针,不会与某个函数绑定,使用不带有圆括号的函数名是访问函数指针,不是调用函数。

在函数中,有两个特殊的对象,arguments和this。

function method() {
// 没有参数的函数
console.log("da");
}


function method(name){
// 带有参数的函数
console.log("da1");
}

函数声明:

使用函数声明语法

function method(name) {
 return name;
}

使用变量初始化函数

var da = function(name){
 return name;
}

使用function构造函数

var da1 = new Function(name);
var add=new Function(‘num1’,’num2’,’return num1+num2’);
// 不推荐这种方式,因为会导致解析两次代码,
// 第一次解析常规ECMAscript代码(全部代码),
// 第二次解析传入构造函数中的字符串,从而影响性能。

参数,把函数的返回值作为参数传递,把函数本身作为参数传递。

var result=add(sum(10),10);


var result=add(sum,10);


//sum是一个函数

return返回值,函数也可以不带有返回值,将返回undefined

函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定。

定义函数,第一,使用函数声明语法,第二,使用函数吧表达式,第三,使用function构造函数。

函数声明与函数表达式的区别

解释器会先读取函数声明,在使其在执行之前可以访问。

函数声明语法

function sum (num1, num2) {
    return num1 + num2;
}

使用函数表达式则必须要等到解析器执行到它所在的代码行时,才会执行,变量声明提前,而值留在原地。

console.log(sum(10,10));
function sum(num1, num2){
    return num1 + num2;
}

在代码执行前,解析器会通过函数声明提升,读取并将函数声明添加到执行环境中,放入到代码树的顶部。

console.log(sum(10,10)); // 报错
var sum = function(num1, num2){
    return num1 + num2;
};

此代码函数位于一个初始化语句中,不是函数声明,不会提前,会把var sum提前,也就是在执行到函数所在语句之前,变量sum中不会保存对函数的引用。

函数是对象来着,函数名是指针。函数名仅仅是指向函数的指针,所以,一个函数对象可以有多个名字。

没有重载的概念

function dada(num){
    return num + 100;
}


function dada(num) {
    return num + 200;
}


var result = dada(100); //300


// 后面的函数覆盖了前面的函数

以上代码实际上与下面的代码没有什么区别:

var da1= function (num){
    return num + 100;
};


da1= function (num) {
    return num + 200;
};


var result = da1(100); //300

函数作为参数传递给另一个函数

要访问函数的指针而不执行函数的话,必须去掉函数名后面的那对圆括号;从一个函数中返回另一个函数。

函数内部的属性

arguments是个类数组对象

传入函数的所有参数,对象有一个叫callee的属性,属性值是一个指针,指向拥有arguments对象的函数本身。

this对象,指向函数执行的环境对象,在哪个对象中执行,就指向哪个对象。

caller属性,保存着调用当前函数的函数的引用

如果是在全局作用域中调用当前函数,它的值为 null。

function outer(){ 
    inner();  
} 
function inner(){ 
    console.log(inner.caller); 
} 


outer(); 
/*输出结果:
ƒunction outer(){ 
    inner();  
}
*/

prototype属性:

是一个对象,通过调用构造函数而创建的一个对象,可以由特定类型的所有实例共享的属性和方法。

toString()方法将函数体转换成对应的字符串。

bind()方法:

会创建一个函数的实例,其 this 值会被绑定到传给 bind() 函数的值。

apply()与call()方法

两个方法的作用都是在特定的作用域中调用函数
实际上就是设置函数内部的this值


apply():接收两个参数


一个是函数运行的作用域,
一个是参数数组,可以是数组,也可以是arguments这个类数组对象;


在使用 call()方法时,传递给函数的参数必须逐个列举出来;

区别仅在于接收参数的方式不同。

apply() 和 call() 真正的本质是用来,扩充函数赖以运行的作用域。

基本包装类型

为了便于操作基本数据类型,ECMAScript还提供了3个特殊的引用数据类型:Boolean、Number和String。

引用类型与基本包装类型的区别,在于它们的对象生命周期不同:


引用类型:


使用new创建引用类型的实例,
在执行数据流离开当前作用域时会一直存储在内存中。


基本包装类型:
自动创建基本包装类型的对象,
只执行一行代码的瞬间之后就会立即销毁。


这意味着在运行时为基本包装类型值添加属性和方法是无效的。

创建Boolean对象

// 定义了一个名为 da 的布尔对象
var da = new Boolean(true); 

如果布尔对象无初始值或者其值为:0、-0、null、""、false、undefined、NaN,那么对象的值为false,否则,其值为true

在布尔表达式中,所有的对象都会被转换为true。

引用类型的布尔值,其实是对象,所以在布尔表达式中使用Boolean 对象都会返回为true。

var da = new Boolean(false); 
alert(typeof da);   // object 


var da1 = false; 
alert(typeof da1);    // boolean 
var da = new Boolean(false); 
alert(da instanceof Boolean); // true 


var da1 = false;
alert(da1 instanceof Boolean);  // false 

toString()方法

功能:根据布尔值返回字符串 "true" 或"false"。

valueOf()方法

功能:返回 Boolean 对象的原始值,就是返回基本类型值

true 或 false。

创建Number对象

Number类型是数字值创建的引用类型。

var da = new Number(10);

toFixed()方法

Number类型的toFixed()方法可以接受一个数值,表示保留的小数的个数(会自动四舍五入)。

toString()方法

将Number数值转换为字符串,该方法接受一个可选参数基数,告诉它返回几进制数值的字符串形式,若省略,则默认基数为10,即十进制。

valueOf()方法

valueOf()返回一个 Number 对象的基本数字值。

创建String对象

String类型是字符串值创建的引用类型。

var da = new String("hello world");
charAt()和 charCodeAt()两个方法都接收一个参数
即基于 0 的字符位置


charAt():
以单字符字符串的形式返回给定位置的那个字符


charCodeAt():
返回给定位置的那个字符的字符编码

截取字符串的方法:

slice()、substr()和 substring()

这三个函数,都不改变原本的字符串,只是在原先的字符串上创建了一个副本,返回操作副本后的值。

slice()
方法会将传入的负值与字符串的长度相加


substr()
方法将负的第一个参数加上字符串的长度,而将负的第二个参数转换为 0


substring()
方法会把所有负值参数都转换为 0。

indexOf()

方法从索引 0 的位置开始查询子字符串

lastIndexOf()

方法从最后一个索引开始查找字符串

trimLeft()和 trimRight()方法,

分别用于删除字符串开头和末尾的空格。

字符串大小写转换的方法:
toLowerCase()、toUpperCase()


var stringValue = "hello world"; 
alert(stringValue.toUpperCase());        
//"HELLO WORLD" 


alert(stringValue.toLowerCase());        
//"hello world"

match()方法

var s = 'hello21 world21';
console.log(s.match(/\d{2}/)); 
// [ '21', index: 5, input: 'hello21 world21' ]

parseInt():转换为整型;

parseFloat():转换为浮点型;

isNaN():判断为是否不是数值;

encodeURI():对字符串进行编码;

decodeURI():

对encodeURI()函数编码过的字符串进行解码。

内置对象:

ECMA-262对内置对象是,由ECMAScript实现提供的,不依赖宿主环境的对象。

程序执行之前就已经存在了。不需要自己定义,不需要自己实例化。

定义了两个内置对象:Global和Math。


CRMEB-慕白寒窗雪 最后编辑于2023-03-17 15:49:01

快捷回复
回复({{post_count}}) {{!is_user ? '我的回复' :'全部回复'}}
回复从新到旧

{{item.user_info.nickname ? item.user_info.nickname : item.user_name}}

作者 管理员 企业

{{item.floor}}# 同步到gitee 已同步到gitee {{item.is_suggest==1? '取消推荐': '推荐'}}
{{item.floor}}#
{{item.user_info.title}}
附件

{{itemf.name}}

{{item.created_at}}  {{item.ip_address}}
{{item.like_count}}
{{item.showReply ? '取消回复' : '回复'}}
删除
回复
回复

{{itemc.user_info.nickname}}

{{itemc.user_name}}

作者 管理员 企业

回复 {{itemc.comment_user_info.nickname}}

附件

{{itemf.name}}

{{itemc.created_at}}   {{itemc.ip_address}}
{{itemc.like_count}}
{{itemc.showReply ? '取消回复' : '回复'}}
删除
回复
回复
查看更多
回复
回复
1011
{{like_count}}
{{collect_count}}
添加回复 ({{post_count}})

相关推荐

CRMEB-慕白寒窗雪 作者
社区运营专员---高冷のBoy | 呆萌のGirl

回答

2025

发布

1771

经验

44160

快速安全登录

使用微信扫码登录
{{item.label}} {{item.label}} {{item.label}} 板块推荐 常见问题 产品动态 精选推荐 首页头条 首页动态 首页推荐
加精
取 消 确 定
回复
回复
问题:
问题自动获取的帖子内容,不准确时需要手动修改. [获取答案]
答案:
提交
bug 需求 取 消 确 定

微信登录/注册

切换手机号登录

{{ bind_phone ? '绑定手机' : '手机登录'}}

{{codeText}}
切换微信登录/注册
暂不绑定
CRMEB客服

CRMEB咨询热线 咨询热线

400-8888-794

微信扫码咨询

CRMEB开源商城下载 开源下载 CRMEB官方论坛 帮助文档
返回顶部 返回顶部
CRMEB客服