day035-thirty-five-20230325-计算符优先级-实例对象与类的属性专用名词-修改this指向-Set类型-类数组转数组-事件委托-轮播图
计算符优先级
- new XXX()----18
- new XXX----17
- XXX.XXX—18 成员访问
阿里巴巴面试题
function Foo() {
getName = function () {
console.log(1);
};
return this;
}
Foo.getName = function () {
console.log(2);
};
Foo.prototype.getName = function () {
console.log(3);
};
var getName = function () {
console.log(4);
};
function getName() {
console.log(5);
}
Foo.getName();//2
getName();//4
Foo().getName();//1
getName();//1
new Foo.getName();//2
new Foo().getName();//3
new new Foo().getName();//3
实例对象与类的属性专用名词
-
类、构造函数上的静态成员 静态成员 静态属性与静态方法
- 访问静态属性,构造函数通过自身直接访问
- 调用静态方法,构造函数通过自身直接调用
-
构造函数的原型对象的成员 公有成员 公有属性与公有方法
- 访问公有属性,实例对象通过原型链__proto__间接访问
- 调用公有方法,实例对象通过原型链__proto__间接调用
-
实例对象上的私有成员 私有成员 私有属性与私有方法
- 访问私有属性,实例对象通过自身直接访问
- 调用私有方法,实例对象通过自身直接调用
-
类构造函数function写法
//Person是一个构造函数,也是一个类,更是一个普通对象,如果不通过new调用,它也是一个普通函数。 const Person = function Person(name) { this.propertyProperty = name;//实例对象的私有属性 this.privatelyFunction = function () {//实例对象的私有方法 console.log("实例对象的私有方法", this.name); }; }; //Person作为普通函数。 Person.staticProperty = "构造函数静态属性";//构造函数的静态属性 Person.staticFunction = function () {//构造函数的静态方法 console.log("构造函数静态方法"); }; //Person是一个构造函数,也是一个类,更是一个普通对象。 Person.prototype.publicProperty = "构造函数原型上的公有属性";//实例对象的公有方法 Person.prototype.publicFunction = function () {//实例对象的公有方法 console.log("构造函数原型上的公有方法"); }; let instance = new Person("实例对象的私有属性-入参");//Person类通过new实例化出来一个实例对象 console.log("打印: 私有属性|-->", instance.propertyProperty);//访问私有属性,实例对象通过自身直接访问 console.log("调用: 私有方法|-->", instance.privatelyFunction());//调用私有方法,实例对象通过自身直接调用 console.log('-----------------') console.log("打印: 公有属性|-->", instance.publicProperty);//访问公有属性,实例对象通过原型链__proto__间接访问 console.log("调用: 公有方法|-->", instance.publicFunction());//调用公有方法,实例对象通过原型链__proto__间接调用 console.log('-----------------') console.log("打印: 静态属性|-->", Person.staticProperty);//访问静态属性,构造函数通过自身直接访问 console.log("调用: 静态方法|-->", Person.staticFunction());//调用静态方法,构造函数通过自身直接调用 console.log('-----------------')
-
类class写法
class Person { constructor(name) { //私有成员 this.propertyProperty = name; this.privatelyFunction = function () { console.log("实例对象的私有方法", this.name); }; } publicFunction = function () { console.log("构造函数原型上的公有方法"); }; static staticProperty = "构造函数静态属性"; static staticFunction = function () { console.log("构造函数静态方法"); }; } Person.prototype.publicProperty = "构造函数原型上的公有属性"; let instance = new Person("实例对象的私有属性-入参");//Person类通过new实例化出来一个实例对象 console.log("打印: 私有属性|-->", instance.propertyProperty);//访问私有属性,实例对象通过自身直接访问 console.log("调用: 私有方法|-->", instance.privatelyFunction());//调用私有方法,实例对象通过自身直接调用 console.log('-----------------') console.log("打印: 公有属性|-->", instance.publicProperty);//访问公有属性,实例对象通过原型链__proto__间接访问 console.log("调用: 公有方法|-->", instance.publicFunction());//调用公有方法,实例对象通过原型链__proto__间接调用 console.log('-----------------') console.log("打印: 静态属性|-->", Person.staticProperty);//访问静态属性,构造函数通过自身直接访问 console.log("调用: 静态方法|-->", Person.staticFunction());//调用静态方法,构造函数通过自身直接调用 console.log('-----------------')
修改this指向
call()、apply()、bind()—Function.prototype上的方法(函数能使用)
作用:修改this的指向
-
如果传入作用新this的入参不是对象,默认会把其转化为包装再作为this。
-
函数.call(新的this,参数1,参数2,…)//参数都是给函数传递参数
- call()/call(undefined)
- this默认window
- 严格模式为undefined
- call(null)
- this默认window
- 严格模式为null
- 调用call()后,函数会执行
- call()/call(undefined)
-
函数.apply(新的this,[参数1,参数2])//参数都是给函数传递参数 apply第二个参数,可以是数组或类数组
- apply()/apply(undefined)
- this默认window
- 严格模式为undefined
- apply(null)
- this默认window
- 严格模式为null
- 调用apply()后,函数会执行
- apply()/apply(undefined)
-
函数.bind(新的this,参数1,参数2,…)//参数都是给函数传递参数
- bind()/bind(undefined)
- this默认window
- 严格模式为undefined
- bind(null)
- this默认window
- 严格模式为null
- 调用bind()后,函数并不会执行,而是一个返回了绑定了作用域与入参的新函数对象
- bind()/bind(undefined)
//"use strict";
function show(n,m){
console.log(this,n,m);
}
show(10,20)//window 10 20
let obj={
name:"lili",
age:18
}
show.call("hello",100,200)
show.call(obj,100,200)
show.call()
show.call(undefined)
show.call(null)
show.bind("hello",100,200)
show.bind(obj,100,200)
show.bind()
show.bind(undefined)
show.bind(null)
show.bind("hello",100,200)()
show.bind(obj,100,200)()
show.bind()()
show.bind(undefined)()
show.bind(null)()
show.apply("hello",[100,200])
show.apply(obj,[100,200])
show.apply()
show.apply(undefined)
show.apply(null)
"use strict";
function show(n,m){
console.log(this,n,m);
}
show(10,20)//undefined 10 20
let obj={
name:"lili",
age:18
}
show.call("hello",100,200)
show.call(obj,100,200)
show.call()
show.call(undefined)
show.call(null)
show.bind("hello",100,200)
show.bind(obj,100,200)
show.bind()
show.bind(undefined)
show.bind(null)
show.bind("hello",100,200)()
show.bind(obj,100,200)()
show.bind()()
show.bind(undefined)()
show.bind(null)()
show.apply("hello",[100,200])
show.apply(obj,[100,200])
show.apply()
show.apply(undefined)
show.apply(null)
练习题
- 取数字数组中的最大值
//方法1:
let arr = [1, 23, 45, 56];
let maxNum = Math.max(...arr);
console.log(maxNum);
//方法2:
let arr = [1, 23, 45, 56];
// Math.prototype.max=function(){//1,23,45,56
// // this--》Math 参数:1,23,45,56
// //....
// }
let maxNum = Math.max.apply(null, arr);
console.log(maxNum);
const fn1 = function fn1() {
console.log(1);
};
const fn2 = function fn2() {
console.log(this, arguments);
console.log(2);
};
fn1.call.call.call.call.call.call(fn2, 10, 20);
//"call方法".call(fn2,10,20)-->fn2.call(10,20)-->fn2函数执行 this-->10 参数20
fn1.call(fn2); //fn1函数执行,this-->fn2 1
fn1.call.call.call(fn2); //总结:两个级两个以上call,就是"call方法"
//"call方法".call(fn2,10,20)---> fn2.call(10,20)
//"call方法".call(fn2)---> fn2.call() --》 fn2函数执行 this-->window
Function.prototype.call(fn2);
// Function.prototype 本质是匿名空函数
// 匿名空函数执行,this--->fn2
Function.prototype.call.call.call(fn2); //2
//"call方法".call(fn2)---》fn2.call()
Function.prototype本质
Function.prototype 本质是一个匿名空函数function(){}
Set类型
-
ES6 新增了Set对象
- new Set() 返回唯一值的set数据,并不是数组
-
new Set()配合Array.from()对数组进行去重
//es6 新增Set对象
let arr=[1,1,1,1,23,34,23,45,56];
let n=new Set(arr);//返回唯一值的set数据,并不是数组
console.log(Array.from(n));
console.log(n);
类数组转数组
- Array.from(类数组)
- […类数组]
- 使用for循环对类数组进行循环
- [].slice.call(类数组)/Array.prototype.slice.call(类数组)
- [].concat.apply([],类数组)/Array.prototype.concat.apply([],类数组)
function show(){
console.log(arguments);
console.log(Array.from(arguments));
}
show(1,2,3,4,5)
function show(){
console.log(arguments);
console.log([...arguments]);
}
show(1,2,3,4,5)
function show(){
console.log(arguments);
let arr=[];
for(let i=0;i<arguments.length;i++){
arr.push(arguments[i])
}
console.log(arr);
}
show(1,2,3,4,5)
function show(){
console.log(arguments);
console.log([].slice.call(arguments));
// console.log(Array.prototype.slice.call(arguments));
}
show(1,2,3,4,5)
function show(){
console.log(arguments);
//console.log([].concat.apply([],arguments));
console.log(Array.prototype.concat.apply([],arguments));
}
show(1,2,3,4,5)
slice底层
Array.prototype.slice=function slice(start=0,end){
//this-->arr 参数:无
if(end===undefined){
end=this.length;
}
let newarr=[]
for(let i=start;i<end;i++){
newarr.push(this[i]);
}
return newarr;
}
let arr=[1,2,3,4,5];
console.log(arr.slice());
类数组如何使用forEach
-
将类数组转成数组直接使用
-
将this改成类数组,调用数组的的forEach方法
[].forEach.call(类数组,()=>{})
function show(){
console.log(arguments);
[].forEach.call(arguments,(item)=>{
console.log(item);
})
}
show(1,2,3,4,5)
function show(){
console.log(arguments);
[...arguments].forEach(item=>{
console.log(item);
})
}
show(1,2,3,4,5)
事件委托
事件委托: 将绑定事件的方法委托给祖先元素,减少事件的绑定,提高性能
- 用e.target来拿到当前被点击的DOM元素
轮播图
浏览器浏览器渲染流程
-
浏览器渲染流程无访问DOM计算性属性时
会放在一个队列里计算好后,统一渲染。 -
浏览器渲染流程有访问DOM计算性属性时
在打印时,会渲染一次。
之后如果再不需要打印时,统一计算,统一渲染。