不要吹灭你的灵感和你的想象力; 不要成为你的模型的奴隶。 ——文森特・梵高
2022年6月10日20:51:25
servlet 生命周期
- Web Client 向servlet发送请求
- servlet 容器创建 HttpRequest ,将Web Client 封装到这个对象
- servlet 容器创建 HttpResponst
- servlet 调用 HttpServlet 的 service 方法 将HttpRequest 和 HttpResponst 作为参数传给HttpServlet
- HttpServlet 通过 HttpRequest 获取 http请求信息
- HttpServlet 通过 HttpResponst 对象方法 和 生成响应数据
- Servlet 把 HttpServlet 响应结果给 Web Client
JSP 和 Servlet 的区别
- JVM识别java类 JSP不是java代码
- JSP更注重页面显示,Servlet更注重逻辑控制
- JSP 有九大内置对象 Servlet没有内置对象
九大内置对象
- PageContext
- request
- responest
- session
- page
- out
- config
- exption
四大作用域
- Pagecontext
- ServletRequest
- Httpsession
- ServletContext
javascrpit 基本数据类型
Number,Object,Null,String,Symbol,Bigint,Null,Undefind
typeof 和 instanceof 的区别
typeof 在比较 对象,数组,null 都会判断为 Object 。 instanceof 判断能否在原型链中找到该对象原型,只能判断引用数据类型 无法判断基本数据类型
constructor
constructor 一判断数据类型,二对象实例通过constructor对象访问它构造函数,但是需要注意,如果对象原型被改变,那么constructor无法正确判断
let g = new Object();
g.prototype = new Array();
g.constructor() === Object
Instanceof 实现
function MyInstanceof(left,right){
let proto = Object.getPrototypeOf(left);
let prototype = right.prototype;
while(true){
if(!proto) return false ;
if(proto === prototype) return true ;
Object.getPrototypeOf(proto);
}
}
为什么0.1+0.2 ! == 0.3,如何让其相等
因为 0.1+0.2 = 0.30000...4 由于JavaScript处理二进制是'舍0入1'的规则
function numberepsilon(num1,num2){
return Math.abs(num1-num2) < Number.EPSILON;
}
numberepsilon(0.1+0.2,0.3) //true
如何获取安全的 undefined 值?
void 0
typeof NaN 的结果是什么?
Number
isNaN 和 Number.isNaN 函数的区别?
- 会尝试将这个参数转换为数值,任何不能被转换为数值的的值都会返回 true,因此非数字值传入也会返回 true ,会影响 NaN 的判断
- Number.isNaN会先判断参数是否是数字类型,是的话再进行判断是否为 NaN
== 操作符的强制类型转换规则?
- 先判断两者类型是否相同 ,相同则比较大小
- 类型不同 进行类型转换
- 判断两者是否在判断 null 和 undefind ,是则返回true
- 判断两者是否在判断 Number 和 String , 是则将String转换为Number 进行判断
其他值到字符串的转换规则?
- null 和 undefind 会直接转换为 'null' 和 'undefind'
- Boolean 如果是 true 返回 'true' , false 返回 'false'
- Number 直接转换
- Symbol 直接转换,只允许显式强制类型转换,隐式转换会报错
- Object 如果是非自定义toString()的话会直接返回对象本身的toString() 如 对象 [object Object] 自定义toString()则返回里面的返回值
2022年6月11日13:11:34
其他值到数字值的转换规则?
- undefined 转换为 NaN
- null 转换为 0
- String 转换数字值就是直接Number()转换,如果是非数字值字符串转换 NaN ,空字符串''转换为0
- Symbol 不允许转换数字 会报错
其他值到布尔类型的值的转换规则?
undefined,null,'',NaN,+0,-0,false 都为false,按逻辑来说除了false列表的值都为真值
|| 和 && 操作符的返回值?
- || 如果是true则返回第一个操作数的值,false返回第二个操作数的值
- && 与||相反 true返回第二个操作数的值,false返回第一个操作数的值
Object.is() 与比较操作符 “===”、“==” 的区别?
- == 会比较数据类型是否相同,不同则类型转换
- === 数据类型不同 则返回false
- Object.is() 和 === 相似,但是有一些特殊情况,两个NaN相等,+0和-0不相等
什么是 JavaScript 中的包装类型?
在调用基本类型的属性或方法时 JavaScript 会在后台隐式地将基本类型的值转换为对象
2022年6月12日08:29:36
JavaScript 中如何进行隐式类型转换?
不得不提到 toPrimitive 这个方法,这是每个值自带的隐式方法,会把每个值(无论是 基本数据类型 还是 对象)转换为 基本数据类型 , 如果改值是 基本数据类型 会返回自身值,对象的话看起来像下面这样
/*
* @obj 对象
* @type 期望的结果类型
*/
ToPrimitive(obj,type)
- Type为Number时会执行以下步骤
1. 会先调用 Obj 的 valueOf 如果结果是原值 返回 则下一步
2. 再调用 Obj 的 toString 同理如上
3. 抛出异常 typeError
- Type为String时会执行以下步骤
1. 先调用 Obj 的 toString 如果结果是原值 返回 则下一步
2. 再调用 Obj 的 valueOf 同理如上
3. 抛出异常 typeError
一般情况下如果是Data类型会默认转换String,其他一律默认转换Number
可以看到上面的不同类型转换只是valueOf和toString的顺序发生了改变
+ 操作符什么时候用于字符串的拼接?
简单来说 如果一方是字符串操作数 则进行字符串拼接,但如果一方是数值类型则将另一方转换为 Number 进行拼接
为什么会有BigInt的提案?
在BigInt之前 Number.MAX_SAFE_INTEGER 在它的范围内可以精确计算(除小数),但是超出这个范围就会计算有误,这对于大数值计算来说很不友好,于是官方推出了BigInt
object.assign和扩展运算法是深拷贝还是浅拷贝,两者区别
扩展运算
let inObj = {
outObj:{
a:0,
b:2
}
}
let b = [...inObj];
b.outObj.a = 2
console.log(inObj.outObj)//{a:2,b:2}
object.assign
let inObj = {
outObj:{
a:0,
b:2
}
}
let b = Object.assign({},inObj.outObj)
b.outObj.a = 2
console.log(inObj.outObj)//{a:2,b:2}
可以看出两者都是浅拷贝
两者区别在于
- 第一个参数的目标对象,第二个参数开始都是源对象,将这些源对象全部合并给目标对象,进行修改,这就触发了ES6的setter
- [...Obj]扩展运算,会把对象或数组,全部复制但是不会复制继承的属性或类属性,会复制Symbol属性
二、ES6
let、const、var的区别
- 块级作用域 : let和const 具备块级作用域 ,var不具备。块级作用域解决了ES5一些问题
- 内层变量被外层变量覆盖
- 用来计算循环的变量会泄露成全局变量
- 变量提升 : let和const 不具备变量升级 只能在声明之后使用, var具备 。
- 全局变量属性 : 浏览器的全局对象是window,Node的全局对象是global。var声明的变量为全局变量,并且会将该变量添加为全局对象的属性,但是let和const不会
- 暂时性死区 : let和const 有暂时性死区,在声明变量之前不可以使用
- 重复性 : var在声明新的变量时会覆盖旧的变量 ,let和const不允许重名
- 指针 :let和const是ES6用来创建的变量,let可以更改指针指向(修改赋值),const 不行
- 初始值 : let 和 var 不需要设置初始值 ,但是const必须设置初始值不然报错
const对象的属性可以修改吗
const只是保证你的指针不会发送改变,但是数据结构的可变性无法控制
如果new一个箭头函数的会怎么样
箭头函数无法new
创建一个函数的过程
- new 一个函数对象
- 构造器的作用域赋值给对象
- 构造器的this指向对象
- 返回新的对象
箭头函数与普通函数的区别
箭头函数更加简洁
- 但参数只有一个时不需要写小括号
- 如果参数有多个只需要逗号分隔
- 但函数体的语句只有一句时不需要写大括号直接返回
- 如果函数体不需要返回值,且只有一句话,可以给这个语句前面加一个void关键字
箭头函数继承来的this指向永远不会改变
call,applay,bind 不会改变箭头函数中this的指向
箭头函数无法被new
箭头函数没有自己的this
箭头函数的this指向哪⾥?
箭头函数没有自己的this,它通过上下文捕获this,因此无法 new 一个箭头函数
扩展运算符的作用及使用场景
- 合并数组
- 作为构造函数的参数序列
- 将字符串转换为真正的数组
- 用于Math,获取指定值
Proxy 可以实现什么功能?
在vue 3.0 中 Proxy替换了原来的Object.defineProperty,用于实现数据响应式
对对象与数组的解构的理解
解构中数据通过位置条件来获取值
对象通过属性名获取值
2022年6月13日08:45:58
如何提取高度嵌套的对象里的指定属性?
用 {属性名:{属性名}} 来进行提取嵌套属性 {class:{stu:{name}}}
对 rest 参数的理解
用于处理参数数量无法确定的情况下使用,可以将分离的参数合成数组
ES6中模板语法与字符串处理
- Includes 用于判断子字符串是否存在于父字符串
- startsWith 判断字符串是否以某中形式开头
- endsWith 判断字符串是否以某种形式结尾
- 以运算形式进行字符串拼接或运算 ${}
三、JavaScript基础
new操作符的实现原理
- 创建一个对象
- 将对象的原型设置为构造函数的propertype
- 将构造函数的this指向对象,指向构造函数的代码
- 如果返回类型是引用类型就返回引用类型,如果是值类型,返回创建的对象
Vue
Vue 解决了什么问题
- 虚拟DOM: 不需要直接操作DOM,而是用Vue提供的方法操作
- 将数据,结构,逻辑 分离开
- 组件化 : 将一个网页拆分为多个组件,这样后期维护方便
Vue 的生命周期(11 个钩子函数)
- beforeCreate 创建前
- Created 创建后
- beforeMount
- Mounted
- beforeUpdate 修改前
- Update 修改后
- activated 组件激活前
- Deactivated 组件激活后
- beforeDestory 销毁前
- destory 销毁后
- errorCaptured
watch、computed 和 methods 的区别
- Methods : 在每次渲染页面时调用
- watch : 监听一个属性,如果这个属性值发送改变就会触发这个事件,没有缓存
- Computed : 当一个属性依赖于另一个属性时 使用Computed ,有缓存,避免重复计算
Vue.js 的特点
- 简洁
- 组件化
- 轻量
- 数据驱动
- 快速
vue-router 有哪几种导航钩子
- 全局钩子
- beforeEach()
- afterEach()
- beforeResolve()
- 单个路由钩子
- beforeEnter()
- beforeLeave()
- 路由钩子
- beforeRouteEnter()
- beforeRouteLeave()
- beforeRouteUpdate()
vue 组件中的 data 为什么是一个函数
因为Object类型是引用数据类型,如果不使用函数,他们会占用一个内存。使用函数的好处就是避免多个组件的data重合。
Vue 中 key 值的作用
v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,在特定索引下显示已被渲染过的每个元素。
为了更加高效的渲染元素
MVVM 的理解
V : View 视图
M : Model 数据模型
VM : ViewModel 视图和数据模型的桥梁
在vue中视图和数据是分离开来,而ViewModel作为桥梁接通View和Model之间的通信,视图层数据改变更新数据模型,数据模型数据改变更新视图层,数据交互是双向的
Vue 组件通讯有哪几种方式
- 父组件向子组件传值时 子组件通过props接收
- 子组件向父组件传值 通过$emit+事件向父组件传值
- provide 和 inject ,官方不推荐使用
- eventBus
- 通过获取组件$refs
- 通过children进行数据通讯
v-for 与 v-if 的优先级
v-for的优先级比v-if的优先级高
vue 的指令
- v-text
- v-html
- v-onces
- v-model
- v-show
- v-for
- v-if
- v-else
- v-else-if
- v-bind
- v-on
- v-slot
v-if 和 v-show 的区别
- v-if 指定某个条件下元素可以被渲染,否则不渲染
- v-show 该元素被渲染出来,但是用户不可见,display:none
Vue 怎么重置 data
Object.assign(this.options.data())
Vue 怎么兼容 IE
使用babel-polyfill
2022年6月14日10:43:36
Tomcat的几种部署方式
- 自动部署 : 将项目直接拖动到webapps目录下自动部署
- Manager App 部署 : 在Tomcat主页 点击Manager App 进入管理 ,选择上传的war文件进行部署
- conf/server.xml 文件部署 修改server.xml 增加Context节点部署
Servlet是线程安全的吗?
Servlet没有线程安全,Servlet默认是单例模式,Web容器只创建一个Servlet,当多线程访问Servlet的时候会出现安全隐患
map和Object的区别
| Map | Object | |
|---|---|---|
| 意外的建 | Map默认没有任何键值,只显示插入的键值 | Object的原型,原型链上的键和自己在对象上设置的键会发生冲突 |
| 键的类型 | Map的键可以是对象,函数,以及基本类型 | Object只支持String和Symbol类型 |
| 键的顺序 | Map的键是有序的,当迭代Map时,键是按照顺序显示 | Object的键是无序的 |
| size | Map可以通过size获取大小 | Object只能通过手动计算 |
| 迭代 | Map可以迭代 | Object需要通过某种手段获取键,再进行迭代 |
| 优化 | Map在删,增键值上优化更好 | Object目前还未优化 |
map和weakMap的区别
Map
-
在ES6中Map类似Object,但是它的键可以是任意值和基本类型。Map有以下方法进行键值操作
- size 获取Map大小
- set() 设置Map键值
- get() 通过键获取值
- delete() 通过键删除值
- clear() 清除所以键值
- hash() Map自带以下方法可以获取键值集合
-
keys() 获取键集合
-
values() 获取值集合
-
entrise
-
ForeEach Map自带的迭代方法
weakMap
- weakMap的键只能是对象,值可以是任意值。weakMap的键是弱引用,因此当引用的对象被清除时,占用的内存也会被清除,weakMap对应的键值也会被自动清除,无需手动。操作键值的方法
- set()
- get()
- delete()
- hash()
JavaScript有哪些内置对象
常用的全局变量值 NaN,Undefind.全局构造函数parseInt(),parseFloat().时间和对象 Data,Object.用于数学计算Math
常用的正则表达式有哪些?
- 匹配QQ号
let g = /^[1-9][0-9]{4,10}$/ - 匹配手机号码
let g = /^[1][34578]\d{9}$/ - 匹配时间 yyyy-mm-dd
let g /^[1-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])&/
对JSON的理解
JSON是轻量型的数据交互格式,可以被所以编码语言读取的数据结构。前端将JSON数据格式转换为json字符串传给后端,后端接收后再转为JSON数据格式,以此来实现前后端数据的一个传递。
JavaScript脚本延迟加载的方式有哪些?
- async 给js脚本添加async属性,让他异步加载
- setTimeout 设置一个定时器来延迟加载js脚本文件
- 让JS最后加载 js 脚本放在文档的底部,来使 js 脚本尽可能的在最后来加载执行
JavaScript 类数组对象的定义?
一个拥有length或是若干个索引的对象称为类数组对象,它和数组显示,但是无法使用数组方法。比如argument和DOM返回的结果就是类数组对象.
常见的类数组转换为数组的方法有这样几种 :
Array.prototype.slice(arrayLike)Array.prototype.splice(arrayLike,0)Array.prototype.concat.apply([], arrayLike);
数组有哪些原生方法?
- 将数组转换为字符串的方法 toString(),toLocalString()。join()让数组以某种字符分隔成字符串
- 尾部操作 push(),pop()
- 首部操作 shift(),unshift()
- 截取某个长度的数组 slice()
- 数组插入 splice()
- 数组方法 map(),filter(),forEach()
- 反转 revers()
常见的位运算符有哪些?其计算规则是什么?
- & '与'运算 两个位都为1结果才返回1
- | '或'运算 两个位其中一个为1 就返回1
- ^ 异或运算 两个相同为0 相异为1
- ~ 取放运算 将二进制取放 0为-1 -1为0
- << 左移运算 将二进制左移若干位,高位丢弃,低位补0
-
右移运算 将二进制右移若干位,正数补0,负数补1,右边丢弃
为什么函数的 arguments 参数是类数组而不是数组?如何遍历类数组?
arguments的属性是0开始递增的数字,以及callee和length属性。它不像数组一样有自己的方法forEach。
以下方法可以遍历类数组
- 用call或apply方法遍历
Array.prototype.forEach.call(arguments,a => console.log(a))
- 运用扩展运算将类数组转换为数组
let ary = [...arguments];
ary.forEach(a => {
console.log(a)
})
2022年6月15日08:34:45
什么是 DOM 和 BOM?
- DOM是文档对象模型,将文档视为一个对象,主要用于处理网页内容的接口
- BOM是浏览器对象模型,将浏览器视为一个对象。BOM的核心是window,它具备两重角色。既通过js访问浏览器的接口,是一个全局对象,定义的变量,对象,函数都是全局对象中的一个属性或方法。DOM最根本的document也是全局对象中的子对象。
对类数组对象的理解,如何转化为数组
类对象具有length属性和若干索引属性的对象,和数组相似,但是它不具备数组常用的方法和属性forEach和reduce。类对象数组一般是arguments和DOM的返回结果。
将类对象转换为数组 :
Array.prototype.slice.call(arrayLike)Array.prototype.splice.call(arrayLike,0)
escape、encodeURI、encodeURIComponent 的区别
- encodeURL 是对整个url进行转义,但是一些特殊含义的字符无法进行转义
- encodeURLComponent 是对url某个组成部分进行转义,特殊字符也可会进行转义
- escape和encodeURL相似,但是在编码格式上不同,escape 是直接在字符的 unicode 编码前加上 %u。encodeURL会先转换成utf-8再加上%
对AJAX的理解,实现一个AJAX请求
AJAX是JavaScript异步通信,通过服务器访问xml从中获取数据,在网页对应部分进行刷新,从而不刷新整个网页
实现AJAX请求
- 先创建一个XMLHttpRequest对象
- open创建一个http请求,第一个参数是请求方法,第二个参数是请求路径,第三个是异步请求和用户认证
- 给XMLHttpRequest添加一个状态监听onreadystatusChange
- send发送请求
let url = 'server.xml'
let xhr = new XMLHttpRequest()
xhr.open("GET",url,true)
xhr.onreadystatuschange = function(){
if(this.readyState !== 4) return ;
if(this.status === 400){
handle(this.response)
}else {
console.error(this.statusText);
}
}
xhr.responseType="json"
xhr.setRequestHeader={"ACCPET":"application/json"}
xhr.send(null)
JavaScript为什么要进行变量提升,它导致了什么问题?
变量提升,无论在函数的哪个位置声明对象,都会被提升到首部,在变量声明之前访问变量也不报错
变量声明好处 :
- 提升性能
- 容错性更好 虽然有优点,但也导致了一些问题。比如下面这行代码,在函数内部访问变量会将变量提神到首部导致访问时是undefind
let tem = new Data()
function fn(){
console.log(tem)
if(false){
tem = 'hello word'
}
}
fn();//undefind
什么是尾调用,使用尾调用有什么好处?
当一个函数执行的底部调用了另一个函数时这就是尾调用。一般情况下一个函数执行完后还会有存留的上下文,调用了另一个函数因为是最后一步了所以这时可以不必再保留当前的执行上下文,从而节省了内存
常见的DOM操作有哪些
DOM 节点的获取
document.getElementById()//通过ID获取
document.getElementByTagName()//通过标签获取
document.getElementByClassName()//通过类名获取
queryselectorAll()//按照css选择器查询
DOM 节点的创建
创建一个新节点,并把它添加到指定节点的后面。 已知的 HTML 结构如下:
<html>
<head>
<title>DEMO</title>
</head>
<body>
<div id="container">
<h1 id="title">我是标题</h1>
</div>
</body>
</html>
要求添加一个有内容的 span 节点到 id 为 title 的节点后面,做法就是:
let container = document.getElementById("container");
let span = document.createElement("span")
span.innerHTML = "芜湖"
container.appendChild(span)
DOM 节点的删除
删除指定的 DOM 节点, 已知的 HTML 结构如下:
<html>
<head>
<title>DEMO</title>
</head>
<body>
<div id="container">
<h1 id="title">我是标题</h1>
</div>
</body>
</html>
需要删除 id 为 title 的元素,做法是:
let container = document.getElementById("container")
let title = document.getElementById("title")
container.removeChild(title)
修改 DOM 元素
修改 DOM 元素这个动作可以分很多维度,比如说移动 DOM 元素的位置,修改 DOM 元素的属性等。 将指定的两个 DOM 元素交换位置, 已知的 HTML 结构如下:
<html>
<head>
<title>DEMO</title>
</head>
<body>
<div id="container">
<h1 id="title">我是标题</h1>
<p id="content">我是内容</p>
</div>
</body>
</html>
现在需要调换 title 和 content 的位置,可以考虑 insertBefore 或者 appendChild:
let container = document.getElementById("container")
let title = document.getElementById("title")
let content = document.getElementById("content")
container.insertBefore(content,title)
use strict是什么意思 ? 使用它区别是什么?
use strict 是JavaScript的严格模式,该模式下,代码更加严格和规范
优点 :
- 避免代码不合理,不严谨之处,减少怪异行为
- 代码运行避免不安全之处,运行速度快
- 为未来的JavaScript作好铺垫 区别 :
- 禁止使用with语句
- 禁止this指向全局对象
- 禁止对象属性名重复
如何判断一个对象是否属于某个类?
- instanceof 判断是否在对象原型链上的任何一个位置
- constructor 不安全,对象类型一旦被更改就无法正确判断
- 通过对象的toString()方法判断返回的值[{class}]属性
强类型语言和弱类型语言的区别
- 强类型语言,java和c++都属于强类型语言,比如当java定义一个整数变量就必须为int。当一个整数变量要转换为字符串时必须强制转换。
- 弱类型语言,JavaScript就属于弱类型语言,var 变量可以是整数类型,小数类型,字符串,对象,数组等。
区别 :
- 弱类型语言相比强类型语言速度更快
- 强类型语言比弱类型更加严谨,避免错误发生
解释性语言和编译型语言的区别
解释性语言 :
- 每次运行都要将源码解释成机器码,运行效率低
- 某个平台提供对应的运行环境就可以运行源码,方便平台移植
- JavaScript和Python都属于解释性语言 编译型语言 :
- 一次性的编译成平台相关的机器语言文件,运行时脱离开发环境,运行效率高
- 一般无法移植平台
- c++和c都是编译型语言
for...in和for...of的区别
- for...in 循环对象的话会把对象的原型循环出来,所以更偏向于遍历数组
- for...of 只会把对象的属性遍历出来,所以更偏向于遍历对象
ajax、axios、fetch的区别
AJAX是一种创建交互式网页应用的网页开发,它可以在不刷新整个网页的情况下,指定某个部分网页刷新。缺点 :
- 是面向mvc编程,不符合mvvm浪潮
- ajax是基于XHR开发实现,XHR本身的架构并不清晰
- 不符合分离原则
- 在调用和配置时非常混乱 fetch不是对ajax进一步的封装,它是基于js,不使用XMLHttpRequest。\
优点:
- 语言更加简洁
- 基于基准Promise实现,支持async/awite
- 更加底层,提供丰富的API
缺点:
- fetch将400,500视为请求成功
- fetch不自带cookie,需要添加配置项
- fetch没有原生监测请求进度
axios 是基于Promise封装的HTTP客户端,它的特点:
- 支持抵御XSRF攻击
- 自动转换json数据
数组的遍历方法有哪些
| 方法 | 是否改变原数组 | 特点 |
|---|---|---|
| forEach() | 是 | 可以改变原数组,没有返回值 |
| map() | 否 | 无法改变原数组,有返回值 |
| filter() | 否 | 过滤数组,返回符合某个条件的数组 |
| find() | 否 | 返回符合添加的第一个数组 |
| some()\every() | 否 | some()有一个为true就返回true。every()有一个为false就返回false |
| reduce | 否 | 对数组正序操作 |
forEach和map方法有什么区别
- forEach没有返回值,map有返回值
- forEach可以改变原数组,map只是对原数组进行克隆再进行改变
2022年6月16日08:10:40
原型与原型链
对原型、原型链的理解
javaScript是使用构造函数创建对象,每一个构造函数都有自己的prototype属性,每个属性都是一个对象,这些对象都是通过构造函数实例共享的属性和方法。每次使用构造函数创建一个空对象时,这个对象内部有一个指针,指针指向prototype属性对应的属性,我们可以通过Object.getPrototypeOf获取对象原型。
当我们访问一个对象的属性时,这个对象内部如果没有这个属性,那么它就会去它对象原型上找,这个原型对象又是一个对象,就一直这样找下去。原型,原型链的尽头是Object.prototype。所以每次创建一个空对象时都会有toString方法。
特征 : JavaScript 对象是通过引用来传递的,创建的每个新对象实体中并没有一份属于自己的原型副本, 每次修改一个对象时,这个对象的原型也会继承这个修改
原型修改、重写
function person(name){
this.name = name
}
person.prototype.getName =function() {
return this.name
}
console.log(p.__proto__ === person.prototype)//ture
console.log(p.__proto__ == p.constructor.prototype)//true
//修改原型
person.prototype={
getName:function(){}
}
console.log(p.__proto__ === person.prototype)//ture
console.log(p.__proto__ == p.constructor.prototype)//false
原型链指向
p.__proto__ // Person.prototype
Person.prototype.__proto__ // Object.prototype
p.__proto__.__proto__ // Object.prototype
p.__proto__.constructor.prototype.__proto__ // Object.prototype
Person.prototype.constructor.prototype.__proto__ // Object.prototype
p.__proto__.constructor // Person
Person.prototype.constructor // Person
原型链的终点是什么?如何打印出原型链的终点?
原型链的终点是Object.prototype.__ proto__ 而Object.prototype.__ proto__ === null 所以原型链最终的终点是null
如何获得对象非原型链上的属性?
使用hasownprototy()
执行上下文/作用域链/闭包
对闭包的理解
闭包就是有权访问另一个函数变量的函数。闭包函数主要有以下两种用途:
- 函数内部可以访问函数外部的变量,外部调用闭包函数,通过调用闭包函数访问变量,可以创建私有变量
- 在函数运行结束时将上下文存留于内存中,由于闭包属性是变量对象引用。所以变量对象不会被回收
对作用域、作用域链的理解
全局作用域
- 在最外层定义的变量拥有全局作用域
- 在全局对象window中的属性也是全局作用域
- 全局变量存在一个弊端,如果过多的全局变量会造成命名冲突 函数作用域
- 指在特点代码块中有效的变量
- 外部无法访问内部,内部可以访问外部
作用域链
当我们访问一个函数变量时,如果这个变量不存在就向上级查找,直到访问到window结束,这就是作用域链