这里写自定义目录标题
JS变量
- 数据类型为对象的注意点:
- 栈堆的概念
- JS对象复制的时候复制的是对象的地址
- 函数的参数,含义是将函数参数指向堆里面的对象
- 面试题
- 相关技术点:
1). 引用变量赋值
2). 内存分析
3). 函数调用传参
4). 运算符的优先级
- 相关技术点:
// 预热一
var obj = { n: 1 };
var obj2 = obj;
obj2.n = 2;
console.log(obj.n); // ?
// 预热二
function fn1(a) {
a.n = 3;
}
fn1(obj);
console.log(obj.n); // ?
// 预热三
// 函数参数a指向obj的地址值{n:1}
// 在函数体内部a指向另外一个地址值{n:4};
// console.log(obj.n)
function fn2(a) {
a = { n: 4 };
}
fn2(obj);
console.log(obj.n); // ?
// 等于赋值表达式是从右向左依次赋值
// 对象属性优先级最高
// 所以先是给a添加一个属性x,暂时没有值
// 其次依次从右向左赋值
var a = { n: 1 };
var b = a;
a.x = a = { n: 2 };
console.log(a.n, b.n); // ? ?
console.log(a.x, b.x); // ? ?
JS变量查找&作用域&作用域链
技术点:
1). 作用域与作用域链
2). 变量查找
//在全局调用fn查找的是全局的变量x
var x = 10;
function fn() {
console.log(x);
}
function show(f) {
var x = 20;
f();
}
show(fn); // ?
// 变量的查找,在自己作用域找,找不到到全局的作用域找,这样形成了一个变量查找的作用域链
var fn = function () {
console.log(fn);
};
fn(); // ?
var obj = {
fn2: function () {
// console.log(fn2)
// 想输出fn2属性的值
console.log(this.fn2); // 如何让其输出obj的fn2?
},
};
obj.fn2(); // ?
JS 中的this
- 难度系数: ★★★
- 技术点:
1). this
2). 闭包
var name = "A";
var object = {
name: "B",
getNameFunc: function () {
return function () {
return this.name; // this是谁? window
};
},
};
console.log(object.getNameFunc()()); //? A
var name2 = "A";
var object2 = {
name2: "B",
getNameFunc: function () {
var that = this; // 缓存this ? object2
return function () {
return that.name2;
};
},
};
console.log(object2.getNameFunc()()); //? B
JS的原型链
- 怎么理解原型?
-
总结内容:
-
所有对象都可以通过__proto__属性找到Object
-
所有函数都可以通过__proto__属性找到Function (fn.prototype.proto)
-
函数的prototype属性是一个对象
-
对象的__proto__属性指向原型,__proto__将对象和原型连接起来组成了原型链
-
并不是所有函数都有prototype属性,
-
原型链就是多个对象通过__proto__的方式连接了起来,这样普通对象可以使用valueOf函数,就是普通对象能够通过原型链找到valueOf函数。
-
- 原型实现继承,在子类的构造函数中调用父类,并使用Parent.call(this,value),在父类的原型上绑定属性和方法,既可以指定参数,也可以让子类继承到父类的属性和方法。
ES6的class继承,使用extends继承父类的属性和方法。
- 面试题
- 难度系数: ★★★
- 技术点:
1). 原型与原型链
2). 对象属性查找
function A() {}
A.prototype.n = 1;
var b = new A();
A.prototype = {
n: 2,
m: 3,
};
var c = new A();
console.log(b.n, b.m, c.n, c.m); // ? ? ? ?
JS表达式
迭代for-in/for-of
for in
遍历对象,遍历对象属性名,以任意顺序遍历对象除Symbol以外的可枚举属性名(遍历属性名)
迭代数组的问题:是数组也有属性名,即数组的下标,如果给数组添加属性名,则也会被迭代
//使用forin迭代数组的问题
var arr = [‘a’,‘b’,‘c’]
arr.name = ‘arr’;
for(let x in arr){
console.log(x)
}
// 0
// 1
// 2
// name
//arr ==> [“a”, “b”, “c”, name: “arr”]
for of
迭代可迭代对象(iterable类型,ES6)
Array,Map,Set
JS运算符
逻辑与或非
- 赋值使用时:会进行类型转换为布尔值
- 逻辑与: A && B ; let a = 1 && 2 ; let b = 0 && 2
-
- 传统运算:都是true则返回true,否则返回false
-
- JS附加功能:寻找第一个真值:可以计算连续表达式的
- 首先会将A转布尔值
- A为false,直接返回A
- A为true,直接返回B
-
- 逻辑或 ||
-
- 传统的||,只要有true则返回true; false|| true等等
-
- JS附加功能:寻找第一个假值:可以计算连续表达式
- 从左到右依次计算操作数
- 都会转换为布尔值,如果为true,就停止计算,返回为true的操作数
- 如果都为false,则返回最后一个操作数;let a = null || undefined || 0; //0 ,所以建议写代码的时候将默认值放在最后面。
- JS附加功能:寻找第一个假值:可以计算连续表达式
- 短路取值,遇到真值的表达式直接返回:let a = 4-4 || 4-1 || 4-2;
-
- 逻辑与: A && B ; let a = 1 && 2 ; let b = 0 && 2
- 逻辑与或一起使用的优先级:
- !大于 && 大于 ||
‘’ 和 '=’
== 抽象(非严格)相等比较
左右两边进行强制类型转换再比较
=== 严格相等比较
左右两边进行类型比较
再进行值比较
比较对象:相同对象(意味着每个对象有同一个引用)
Object.is
与三等号类似
比较对象相同对象(意味着每个对象有同一个引用)
与三等的区别: 在于比较NaN,+0/-0之间
NaN == NaN // false
NaN === NaN // false
Object.is(NaN,NaN) // true
Object.is(+0,-0); //false
+0 === -1 //true
3、可选链操作符和空值合并运算符
?.
??
// 仅到左侧的值为null或undefined的时候;设置默认值
var obj = {};
let str = Obj?.name ?? ‘hello world’
展开运算符和剩余参数
// 展开语法
var arr = [1,2,3] ;
function sum(a,b,c){
return a+b+c
};
// 类似于apply
sum.apply(null,arr)
function sum(…theArgs) {
return theArgs.reduce((previous, current) => {
return previous + current;
});
}
console.log(sum(1, 2, 3));
// expected output: 6