算法
背包问题-可装同样物件
const knapsack = (weights:number[], values:number[], total:number) => {
var n = weights.length;
var f = [[]];
f[-1] = new Array(total+1).fill(0);
for(var i=0; i<n; i++){
f[i] = new Array(total).fill(0);
for(var j=0; j<=total; j++){
if(j < weights[i]){
f[i][j] = f[i-1][j];
}else{
for(var k = 0; k*weights[i] <= j; k++){
f[i][j] = Math.max(f[i-1][j], f[i-1][j-k * weights[i]] + values[i] * k);
}
}
}
}
var totalWeight = 0,
j = total;
for(var i=n;i--;){
if(f[i][j] > f[i-1][j]){
var k = 0;
while(f[i][j] > f[i-1][j]){
k++;
j -= weights[i];
}
totalWeight += weights[i] * k;
console.log(`选择物品:${k} 个 ${i};重量为:${weights[i] * k};价值为:${values[i] * k}`);
}
}
console.log(`背包最大承重:${total};实际重量:${totalWeight};最大价值:${f[n-1][total]}`)
}
knapsack([2, 3, 4, 7], [1, 3, 5, 9], 10)
this
js 是词法作用域,这个前一章已经大概介绍了,这个是作用域的概念,this 是在函数被调用时发生的绑定,this 可以理解成作用域的一部分,它的指向完全取决于函数在哪里调用的。
this 的四种绑定规则
既然 this 是在函数执行的时候才会被绑定,那么就有它的绑定规则,下面介绍四种绑定规则。
默认绑定
const foo = () => {
console.log(this.a) // 输出 a
}
var a = 2; // 变量声明到全局对象中
foo();
默认绑定我们可以看做隐式绑定的一种特殊情况,实际上是 window.foo(), 所以我们可以理解成被绑定到全局对象中,如果是在浏览器中,就会被绑定到全局对象中。
隐式绑定
const foo = () => {
console.log(this.a);
}
let obj1 = {
a: 1,
foo
};
let obj2 = {
a: 2,
foo
}
obj1.foo(); // 输出 1
obj2.foo(); // 输出 2
遵循函数谁是调用者,this 就会指向谁。所以这里的 this 调用方就是两个 obj。
显式绑定
- call(this, arg1, arg2, …)
- apply(this, [arg1, arg2, …])
- bind(this, arg1, arg2)
前两个是在执行的时候指定 this 的指向。bind 是永久性将 this 指向到某个对象上。内部实现也是用 call 或者 apply 实现的。
new 绑定
js 没有类的概念,实现类和继承都是基于原型链的,代码实现就是构造函数。实例化的时候会使用 new 来得到一个实例。实际上是 return 了当前构造函数的 this。
class Foo{
construtor(){
return this;
}
}
var foo = new Foo();
foo 拿到了构造函数的 this 的引用,就可以根据 this + 原型链 调用 Foo 的构造函数的方法和原型链上的方法了。
优先级
new > 显式绑定 > 隐式绑定 > 默认绑定