前言
在写业务的时候最近碰到一个坑(也不算吧,就是忙着写业务的时候没想起来这回事,呜呜~),写了一个函数之后传了两个数组进去结果发现传进去的数组当函数执行完之后就改变了。
最后解决方法是在传参之后在函数里深拷贝一份参数
本函数的作用:根据两个数组[x1,x2,x3,…],[y1,y2,y3…]求拟合方程,并求出最大值y和最大值对应的x值
// 深拷贝
function deepClone(obj) {
let objClone = Array.isArray(obj) ? [] : {};
if (obj && typeof obj === "object") {
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
//判断ojb子元素是否为对象,如果是,递归复制
if (obj[key] && typeof obj[key] === "object") {
objClone[key] = this.deepClone(obj[key]);
} else {
//如果不是,简单复制
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
export function getMaxData(arr1, arr2) { //array1为含水量 ,array2为干密度
let array1 = deepClone(arr1)
let array2 = deepClone(arr2)
let x = new Array();
let xs = new Array();
let j = array1.length;
let pd, w;
let max;
let s;
let max_x = 0;
let min_x = 0;
max_x = Math.max(...array1);
min_x = Math.min(...array1);
if (!(max_x >= min_x || min_x >= 0)) {
min_x = 0;
max_x = 20;
}
if (max_x - min_x > 100) {
return false;
}
let global_msg = "线性方程数组:";
if (array2.length > 0) {
for (let i = 0; i <= j - 1; i++) {
x[i] = new Array();
for (let k = 0; k <= j - 1; k++) {
x[i][k] = Math.pow(array1[i], j - 1 - k);
}
}
xs = Gauss(x, array2);
global_msg += "多项式系数:";
for (let i = 0; i < xs.length; i++) {
global_msg += xs[i] + ",";
}
max = Newton(xs, min_x, max_x, 0.01);
w = max.split(";")[0];
pd = max.split(";")[1];
}
else {
pd = "";
w = "";
}
return { maxValue: Number(pd), maxX: Number(w) }
}
// 高斯列主元消去法求解线性方程组
// 返回数组解
function Gauss(x, y) {
var xs = new Array();
// 变量区域 i表示行,k表示列
var i, j, k, tmp, ik, n, mik;
n = x.length;
// 消元
for (let k = 0; k < n; k++) {
// 选列主元
mik = -1;
for (let i = k; i < n; i++) {
if (Math.abs(x[i][k] * 1) > mik) {
mik = Math.abs(x[i][k] * 1);
ik = i; //当前列系数最大的行
}
}
for (let j = k; j < n; j++) {
tmp = x[ik][j];
x[ik][j] = x[k][j];
x[k][j] = tmp;
}
tmp = y[k]; y[k] = y[ik]; y[ik] = tmp; //把当前行数据和最大列的系数对换
// 消元
y[k] = y[k] * 1 / (x[k][k] * 1);
for (let i = n - 1; i >= k; i--) {
x[k][i] = (x[k][i] / x[k][k]);
}
for (let i = k + 1; i < n; i++) {
y[i] = y[i] - x[i][k] * y[k];
for (let j = n - 1; j >= k; j--) {
x[i][j] = x[i][j] - x[i][k] * x[k][j];
}
}
}
// 回代
var s = 0;
xs[n - 1] = y[n - 1];
for (let i = n - 2; i >= 0; i--) {
s = y[i];
for (let j = i + 1; j < n; j++) {
s = s - xs[j] * x[i][j];
}
xs[i] = s;
}
return xs;
}
/*牛顿迭代求多项式的最大值*/
function Newton(xs, min, max, step) {
console.log(xs, min, max, step, "step");
var n = xs.length;
var s = 0;
var tmp = 1;
var y;
var x;
for (let i = min; i + step < max; i = i + step) {
// 求多次方
for (let j = 0; j < n; j++) {
tmp = Math.pow(i, n - 1 - j)
s = s + tmp * xs[j];
tmp = 1;
}
if (i == min) {
x = i;
y = s;
s = 0;
continue;
}
if (s > y) {
x = i;
y = s;
}
s = 0;
}
console.log(x, "x", y, "y");
return x + ";" + y;
}
总结
在JavaScript中,因为其基于原型的继承和动态的数据类型,所有参数的传递方式可以被视为“值传递”。这意味着当你将一个参数传递给一个函数时,你实际上传递的是一个值的副本。如果这个值是一个对象,那么副本实际上是对原对象的引用(地址)。
简单来说:
所有基本类型(例如:Number, String, Boolean, undefined, null)按值传递。
所有对象类型(例如:Object, Array, Function)按引用传递。