20230325----重返学习-计算符优先级-实例对象与类的属性专用名词-修改this指向-Set类型-类数组转数组-事件委托-轮播图

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()后,函数会执行
  • 函数.apply(新的this,[参数1,参数2])//参数都是给函数传递参数 apply第二个参数,可以是数组或类数组

    • apply()/apply(undefined)
      • this默认window
      • 严格模式为undefined
    • apply(null)
      • this默认window
      • 严格模式为null
    • 调用apply()后,函数会执行
  • 函数.bind(新的this,参数1,参数2,…)//参数都是给函数传递参数

    • bind()/bind(undefined)
      • this默认window
      • 严格模式为undefined
    • bind(null)
      • this默认window
      • 严格模式为null
    • 调用bind()后,函数并不会执行,而是一个返回了绑定了作用域与入参的新函数对象
//"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);

类数组转数组

  1. Array.from(类数组)
  2. […类数组]
  3. 使用for循环对类数组进行循环
  4. [].slice.call(类数组)/Array.prototype.slice.call(类数组)
  5. [].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

  1. 将类数组转成数组直接使用

  2. 将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计算性属性时
    在打印时,会渲染一次。
    之后如果再不需要打印时,统一计算,统一渲染。

进阶参考

  1. 运算符优先级 - MDN文档

你可能感兴趣的:(重返学习,学习,javascript,前端)