js
this指向
- 看函数的调用方式,而不是他的定义时候
分类
- 构造函数==> new时候创建的对象
- 对象的方法内部 ==》调用方法的对象
- 事件处理函数 ==》绑定的事件
- 箭头函数 ==》没有自己的this
- 其他函数(全局的/局部的) ==》匿名的就是window
- 定时器函数 ==》window
- 立即执行函数==》window
- 正常的全局命名函数==》window (无论是否嵌套在函数内部)
改变this指向
- call
- apply
- bind
- 箭头
call apply bind 使用及区别
-
参数上限个数不同,传递参数的形式也不同;
-
返回给新的函数,共用一个函数体;
// call //正常提供参数 var obj = { value: "vortesnail", }; function fn(x,y) { log(x+y) console.log(this.value); } fn.call(obj,4,5);// 改变this指向以及执行fn; // apply 使用数组方式提供参数 var Person = { name: "zhangsan", age: 19 } function aa(x, y) { console.log(x + "," + y); console.log(this); console.log(this.name); } aa.apply(Person, [4, 5]);//Person // bind 创建一个新的函数需要手动调用。 var Person = { name: "zhangsan", age: 19 } function aa(x, y) { console.log(x + "," + y); console.log(this); console.log(this.name); } aa.bind(Person, 4, 5); //只是更改了this指向,没有输出 aa.bind(Person, 4, 5)(); //this指向Person--4,5 Person{}对象 zhangsan
箭头函数
- 没有prototype属性;
- 没有this指向,指向最近的作用域。
- 没有arguments参数;不能使用new关键字;
数据类型
区别
- 存储到堆与栈中不同:
- 基础数据类型存储再栈中;
- 复杂数据类型数据存入堆,堆的地址值存入栈;
常见的类型:
数据类型 | 类型 |
---|---|
简单数据类型 | 数值number,字符string,布尔Boolean,空null,Symbol,bigint |
复杂数据类型 | 对象,(Array,object),Set,Map |
数组方法 15+8
方法类型 | 方法 | 返回值 |
---|---|---|
增删 | push(),pop(),unshift(),shift() | 修改后数组长度 |
截取/插入 | splice(开始索引,个数,(插入元素)) | 返回新的数组 |
排序 | reverse(),sort(function(a,b){return a-b}) | 返回排序后数组/改变原数组/从小到大 |
合并 | concat() | 合并后的新数组 |
转字符串 | join('') | 某个符号连接的字符 |
复制 | slice(开始索引号(>=),结束索引(<)) | 复制后的新数组/不改变原数组 |
索引查询 | indexOf('查询字符','第几次出现'),lastIndexOf | 返回被查寻得字符第几次(最后几次)出现得位置索引号,不存在的返回-1 |
数组包含 | includes('查询字符') | true/false |
遍历 | for(),for in,for of | |
新增 | forEach | 无返回值 |
映射 | map | 操作后的值 |
过滤 | filter | 满足条间的新数组 |
判断所有boolean | every | 判断是否满足条件,其中一个不满足都会返回false |
判断boolean | some | 至少一个满足条件返回true |
查找值 | find | 返回满足条件的第一个值 |
查找索引 | findIndex | 返回满足条件的第一个索引 |
累计 | ary.reduce(((prev,item)=>return prev + item),1000) | 回调累计计算 |
- reduce 详解
let ary =[3,4,5,6]
let sum=ary.reduce(function(start,b){
console.log(start,b);
return start+b
},1000)
console.log(ary,sum);
字符串方法 15
类型 | 方法名 | 功能 |
---|---|---|
拼接 | concat() | 合并字符串 |
index查unicode | charCodeAt(x) | 返回字符串中x位置处字符的unicode值 |
str查index | charAt(x) | 返回字符串中x字符的位置,下标从0开始 |
u转str | fromCharcode() | 将一组Unicode码转换为字符 |
匹配 | indexOf(substr, [start]) | 返回指定的字符串值首次出现的位置。没有匹配返回 -1。 |
反匹配 | lastIndexOf(substr, [start]) | 返回指定文本最后一次出现的索引, 未找到,则返回-1。 |
替换all | replaceAll(oldStr,newStr) | 替换查询到的所有匹配字符串,没有则返回null。 |
替换 | replace(oldStr,newStr) | 替换查询到到的一个匹配字符串; |
字符转数组 | split(delimiter, [limit]) | 按照某个分割符间隔为数组 |
截取 | substr(start, [length]) | start 截取length个字符。没指定 length,则返回到结尾。 |
复制 | substring(【start,stop)) | 两个指定下标之间的字符. |
转小写 | toLowerCase() | 把字符串转换为小写。 |
转大写 | toUpperCase() | 把字符串转换为大写。 |
包含 | includes() | 检查字符串是否包含指定的字符串或字符。 |
去空 | trim() | 从一个字符串的两端删除空白字符。 |
闭包
定义:
- 闭包:闭包就是函数和周围状态的组合;JS中内层函数(闭包)可以访问外层函数的变量,内部私有变量不受外界干扰,起到保护和保存的作用,我们把这个特性称作闭包。
产生步骤:
- 函数内部返回一个新函数
- 外部函数定义一个局部变量
- return 的函数内使用此局部变量
特点/功能:
- 局部变量常驻内存,像全局变量
- 避免使用全局变量,防止全局污染
- 私有化变量,隔离作用域,保护私有变量
- 操作其他函数内部,回调;
- 外部函数访问内部变量,访问变量
缺点:
- 内层函数引用外层函数变量,占用内存后,不释放内存导致内存泄漏;
使用场景:
-
防抖节流。
-
函数外部调用函数内部 (内部函数被引用是,会保留其作用域链)
function box(){ **let a=1; return function(){ a++ log a }** } let fn = box() //fn是box的内部匿名函数 fn() // fn可以使用内部局部变量的a,a=2,3,4...每调用一次 值都不同; // 如果外层函数直接写a=1 ,a++,不return则每一次的值都相同为2; // 此时全局调用fn(),使用外层的变量a也就是**函数外部调用函数内部。**
ES5+
原型
-
构造函数/显示原型属性/隐式原型属性/原型(原型对象)/显示原型/隐式原型
function Person(){ //this.prototype ={} this.name='zhou' } let p1=new Person() //this.__ proto __ ==Fn.prototype log Person.prototype // 显示原型==原型==prototype 1. log p1.__proto__ // 隐示原型==__proto__ 2. p1.__proto__ ==Person.prototype //true 3.
原型(对象)/隐式原型
-
定义:
- 每个函数Person都有的prototype属性显示原型属性;
-
显示原型属性指向空的Object对象;
-
该属性的值指向的对象、也称之为原型(原型对象);
-
存放属性和方法
-
每一个实例对象p1都有个__ proto __称之为隐式原型属性;
-
对象的隐式原型的值为其对应的构造函数的显示原型的值(都存放的地址值)
-
- 每个函数Person都有的prototype属性显示原型属性;
生成时间
-
prototype生成时间:
- Person函数创建时生成的
- 创建Person时:this.prototype ={}
-
__proto__生成时间:
- new 实例对象时生成的
- new 实例时:this.__ proto __ ==Fn.prototype
- 创建prototype时指向的原型对象的值为地址值 ==创建proto
-
画图:
-
尽量操作显示原型上的属性或方法/而不要手动修改隐式原型上的方法属性;
深/浅拷贝
定义:
- 浅拷贝:拷贝对象,只拷贝浅层的地址值,属性值未能拷贝;
实现/验证:
-
let obj ={ uname:'zhou', child:{age:18} } // 浅拷贝: let obj2.uname=obj.uname; let obj2.child=obj.child; obj=obj2 //false; // 深拷贝: let obj3={ uname:obj.uname, child:obj.child } obj.child == obj2.child // true; obj.child == obj3.child // true;
-
浅拷贝:
-
实现:自己封装函数遍历,展开运算符,assign,lodash(第三方js库)
-
let obj1 = { name: '张三', age: 18, child: { name: '张三丰' } } // 1- 自己封装函数遍历 function clone(obj) { // 遍历 obj 里面的属性名 和 属性值-- 添加到 一个新的对象中 let resObj = {} for (let key in obj) { //key 属性名 // value 属性值 let value = obj[key] // 添加到 一个新的对象中 // 如果value 是一个对象--》child ,直接把地址给了 resObj resObj[key] = value; } return resObj } // 验证: let obj2 = clone(obj1); console.log(obj2); console.log(obj1 === obj2);//false console.log(obj1.child === obj2.child);//t // 2- 展开运算符(多) // ...obj1 // 验证: let obj3 = { ...obj1 }; console.log(obj1 === obj3);//false console.log(obj1.child === obj3.child);//true
-
3- Object.assgin(obj1,obj2)
Object.assgin({},obj2)
把后面对象的成员(属性和方法)都添加到 前一个对象中
返回的是第一个对象
let obj4 = Object.assign({}, obj1);
console.log(obj4);
console.log(obj4 === obj1);//false
console.log(obj4.child === obj1.child);//t
4- lodash --第三方 js工具库(封装了很多函数)
// https://www.lodashjs.com/docs/lodash.clone#_clonevalue
// https://www.bootcdn.cn/lodash.js/ 去这个免费cdn网站找 lodash的js文件
// 引入到页面中
-
深拷贝:
- 实现:自己封装递归
原型链(隐式原型链)
定义:
- 访问一个对象(实例对象)的属性时先在自身上寻找找到返回;否则再沿着__ proto__,去隐式原型对象上寻找,找到则返回,否则undefined;尽头是Object原型对象Object.prototype;沿着隐式原型
作用:
-
查找一个对象的属性(不是变量)和方法的;
-
查变量去作用域链(作用域内,逐级向外侧回溯);
作用域链:
- 每个执行环境都有与之关联的变量,保证执行环境变量函数有序性,向下访问变量不被允许;作用域则是变量函数的访问范围
(构造函数)new做了什么
let this ={}; //自动创建this对象;创建空对像,this变量引用
this.__proto__ = Fn.prototype;//继承原型
return this// 返回this
标签:面试题,console,函数,JavaScript,ES5,原型,child,let,log
From: https://www.cnblogs.com/saturday-blog/p/18591919