原型链指向
p.__proto__ // Person.prototypePerson.prototype.__proto__ // Object.prototypep.__proto__.__proto__ //Object.prototypep.__proto__.constructor.prototype.__proto__ // Object.prototypePerson.prototype.constructor.prototype.__proto__ // Object.prototypep1.__proto__.constructor // PersonPerson.prototype.constructor // Person
介绍下 promise 的个性、优缺点,外部是如何实现的,入手实现 Promise
1)Promise根本个性
- 1、Promise有三种状态:pending(进行中)、fulfilled(已胜利)、rejected(已失败)
- 2、Promise对象承受一个回调函数作为参数, 该回调函数承受两个参数,别离是胜利时的回调resolve和失败时的回调reject;另外resolve的参数除了正常值以外, 还可能是一个Promise对象的实例;reject的参数通常是一个Error对象的实例。
- 3、then办法返回一个新的Promise实例,并接管两个参数onResolved(fulfilled状态的回调);onRejected(rejected状态的回调,该参数可选)
- 4、catch办法返回一个新的Promise实例
- 5、finally办法不论Promise状态如何都会执行,该办法的回调函数不承受任何参数
- 6、Promise.all()办法将多个多个Promise实例,包装成一个新的Promise实例,该办法承受一个由Promise对象组成的数组作为参数(Promise.all()办法的参数能够不是数组,但必须具备Iterator接口,且返回的每个成员都是Promise实例),留神参数中只有有一个实例触发catch办法,都会触发Promise.all()办法返回的新的实例的catch办法,如果参数中的某个实例自身调用了catch办法,将不会触发Promise.all()办法返回的新实例的catch办法
- 7、Promise.race()办法的参数与Promise.all办法一样,参数中的实例只有有一个率先扭转状态就会将该实例的状态传给Promise.race()办法,并将返回值作为Promise.race()办法产生的Promise实例的返回值
- 8、Promise.resolve()将现有对象转为Promise对象,如果该办法的参数为一个Promise对象,Promise.resolve()将不做任何解决;如果参数thenable对象(即具备then办法),Promise.resolve()将该对象转为Promise对象并立刻执行then办法;如果参数是一个原始值,或者是一个不具备then办法的对象,则Promise.resolve办法返回一个新的Promise对象,状态为fulfilled,其参数将会作为then办法中onResolved回调函数的参数,如果Promise.resolve办法不带参数,会间接返回一个fulfilled状态的 Promise 对象。须要留神的是,立刻resolve()的 Promise 对象,是在本轮“事件循环”(event loop)的完结时执行,而不是在下一轮“事件循环”的开始时。
- 9、Promise.reject()同样返回一个新的Promise对象,状态为rejected,无论传入任何参数都将作为reject()的参数
2)Promise长处
①对立异步 API
- Promise 的一个重要长处是它将逐步被用作浏览器的异步 API ,对立当初各种各样的 API ,以及不兼容的模式和手法。
②Promise 与事件比照
- 和事件相比拟, Promise 更适宜解决一次性的后果。在后果计算出来之前或之后注册回调函数都是能够的,都能够拿到正确的值。 Promise 的这个长处很天然。然而,不能应用 Promise 解决屡次触发的事件。链式解决是 Promise 的又一长处,然而事件却不能这样链式解决。
③Promise 与回调比照
- 解决了回调天堂的问题,将异步操作以同步操作的流程表达出来。
- ④Promise 带来的额定益处是蕴含了更好的错误处理形式(蕴含了异样解决),并且写起来很轻松(因为能够重用一些同步的工具,比方 Array.prototype.map() )。
3)Promise毛病
- 1、无奈勾销Promise,一旦新建它就会立刻执行,无奈中途勾销。
- 2、如果不设置回调函数,Promise外部抛出的谬误,不会反馈到内部。
- 3、当处于Pending状态时,无奈得悉目前停顿到哪一个阶段(刚刚开始还是行将实现)。
- 4、Promise 真正执行回调的时候,定义 Promise 那局部实际上曾经走完了,所以 Promise 的报错堆栈上下文不太敌对。
4)简略代码实现
最简略的Promise实现有7个次要属性, state(状态), value(胜利返回值), reason(错误信息), resolve办法, reject办法, then办法
class Promise{ constructor(executor) { this.state = 'pending'; this.value = undefined; this.reason = undefined; let resolve = value => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; } }; let reject = reason => { if (this.state === 'pending') { this.state = 'rejected'; this.reason = reason; } }; try { // 立刻执行函数 executor(resolve, reject); } catch (err) { reject(err); } } then(onFulfilled, onRejected) { if (this.state === 'fulfilled') { let x = onFulfilled(this.value); }; if (this.state === 'rejected') { let x = onRejected(this.reason); }; }}
5)面试够用版
function myPromise(constructor){ let self=this; self.status="pending" //定义状态扭转前的初始状态 self.value=undefined;//定义状态为resolved的时候的状态 self.reason=undefined;//定义状态为rejected的时候的状态 function resolve(value){ //两个==="pending",保障了了状态的扭转是不不可逆的 if(self.status==="pending"){ self.value=value; self.status="resolved"; } } function reject(reason){ //两个==="pending",保障了了状态的扭转是不不可逆的 if(self.status==="pending"){ self.reason=reason; self.status="rejected"; } } //捕捉结构异样 try{ constructor(resolve,reject); }catch(e){ reject(e); } }myPromise.prototype.then=function(onFullfilled,onRejected){ let self=this; switch(self.status){ case "resolved": onFullfilled(self.value); break; case "rejected": onRejected(self.reason); break; default: }}// 测试var p=new myPromise(function(resolve,reject){resolve(1)}); p.then(function(x){console.log(x)})//输入1
6)大厂专供版
const PENDING = "pending"; const FULFILLED = "fulfilled"; const REJECTED = "rejected";const resolvePromise = (promise, x, resolve, reject) => { if (x === promise) { // If promise and x refer to the same object, reject promise with a TypeError as the reason. reject(new TypeError('循环援用')) } // if x is an object or function, if (x !== null && typeof x === 'object' || typeof x === 'function') { // If both resolvePromise and rejectPromise are called, or multiple calls to the same argument are made, the first call takes precedence, and any further calls are ignored. let called try { // If retrieving the property x.then results in a thrown exception e, reject promise with e as the reason. let then = x.then // Let then be x.then // If then is a function, call it with x as this if (typeof then === 'function') { // If/when resolvePromise is called with a value y, run [[Resolve]](promise, y) // If/when rejectPromise is called with a reason r, reject promise with r. then.call(x, y => { if (called) return called = true resolvePromise(promise, y, resolve, reject) }, r => { if (called) return called = true reject(r) }) } else { // If then is not a function, fulfill promise with x. resolve(x) } } catch (e) { if (called) return called = true reject(e) } } else { // If x is not an object or function, fulfill promise with x resolve(x) }}function Promise(excutor) { let that = this; // 缓存以后promise实例例对象 that.status = PENDING; // 初始状态 that.value = undefined; // fulfilled状态时 返回的信息 that.reason = undefined; // rejected状态时 回绝的起因 that.onFulfilledCallbacks = []; // 存储fulfilled状态对应的onFulfilled函数 that.onRejectedCallbacks = []; // 存储rejected状态对应的onRejected函数 function resolve(value) { // value胜利态时接管的终值 if(value instanceof Promise) { return value.then(resolve, reject); } // 实际中要确保 onFulfilled 和 onRejected ⽅办法异步执⾏行行,且应该在 then ⽅办法被调⽤用的那⼀一轮事件循环之后的新执⾏行行栈中执⾏行行。 setTimeout(() => { // 调⽤用resolve 回调对应onFulfilled函数 if (that.status === PENDING) { // 只能由pending状态 => fulfilled状态 (防止调⽤用屡次resolve reject) that.status = FULFILLED; that.value = value; that.onFulfilledCallbacks.forEach(cb => cb(that.value)); } }); } function reject(reason) { // reason失败态时接管的拒因 setTimeout(() => { // 调⽤用reject 回调对应onRejected函数 if (that.status === PENDING) { // 只能由pending状态 => rejected状态 (防止调⽤用屡次resolve reject) that.status = REJECTED; that.reason = reason; that.onRejectedCallbacks.forEach(cb => cb(that.reason)); } }); } // 捕捉在excutor执⾏行行器器中抛出的异样 // new Promise((resolve, reject) => { // throw new Error('error in excutor') // }) try { excutor(resolve, reject); } catch (e) { reject(e); }}Promise.prototype.then = function(onFulfilled, onRejected) { const that = this; let newPromise; // 解决理参数默认值 保障参数后续可能持续执⾏行行 onFulfilled = typeof onFulfilled === "function" ? onFulfilled : value => value; onRejected = typeof onRejected === "function" ? onRejected : reason => { throw reason; }; if (that.status === FULFILLED) { // 胜利态 return newPromise = new Promise((resolve, reject) => { setTimeout(() => { try{ let x = onFulfilled(that.value); resolvePromise(newPromise, x, resolve, reject); //新的promise resolve 上⼀一个onFulfilled的返回值 } catch(e) { reject(e); // 捕捉前⾯面onFulfilled中抛出的异样then(onFulfilled, onRejected); } }); }) } if (that.status === REJECTED) { // 失败态 return newPromise = new Promise((resolve, reject) => { setTimeout(() => { try { let x = onRejected(that.reason); resolvePromise(newPromise, x, resolve, reject); } catch(e) { reject(e); } }); }); } if (that.status === PENDING) { // 期待态// 当异步调⽤用resolve/rejected时 将onFulfilled/onRejected收集暂存到汇合中 return newPromise = new Promise((resolve, reject) => { that.onFulfilledCallbacks.push((value) => { try { let x = onFulfilled(value); resolvePromise(newPromise, x, resolve, reject); } catch(e) { reject(e); } }); that.onRejectedCallbacks.push((reason) => { try { let x = onRejected(reason); resolvePromise(newPromise, x, resolve, reject); } catch(e) { reject(e); } }); }); }};
请实现 DOM2JSON 一个函数,能够把一个 DOM 节点输入 JSON 的格局
题目形容:
<div> <span> <a></a> </span> <span> <a></a> <a></a> </span></div>把上诉dom构造转成上面的JSON格局{ tag: 'DIV', children: [ { tag: 'SPAN', children: [ { tag: 'A', children: [] } ] }, { tag: 'SPAN', children: [ { tag: 'A', children: [] }, { tag: 'A', children: [] } ] } ]}
实现代码如下:
function dom2Json(domtree) { let obj = {}; obj.name = domtree.tagName; obj.children = []; domtree.childNodes.forEach((child) => obj.children.push(dom2Json(child))); return obj;}
扩大思考:如果给定的不是一个 Dom 树结构 而是一段 html 字符串 该如何解析?
那么这个问题就相似 Vue 的模板编译原理 咱们能够利用正则 匹配 html 字符串 遇到开始标签 完结标签和文本 解析结束之后生成对应的 ast 并建设相应的父子关联 一直的 advance 截取残余的字符串 直到 html 全副解析结束
对HTML语义化的了解
语义化是指依据内容的结构化(内容语义化),抉择适合的标签(代码语义化)。艰深来讲就是用正确的标签做正确的事件。
语义化的长处如下:
- 对机器敌对,带有语义的文字表现力丰盛,更适宜搜索引擎的爬虫爬取无效信息,有利于SEO。除此之外,语义类还反对读屏软件,依据文章能够主动生成目录;
- 对开发者敌对,应用语义类标签加强了可读性,构造更加清晰,开发者能清晰的看出网页的构造,便于团队的开发与保护。
常见的语义化标签:
<header></header> 头部<nav></nav> 导航栏<section></section> 区块(有语义化的div)<main></main> 次要区域<article></article> 次要内容<aside></aside> 侧边栏<footer></footer> 底部
对浏览器的了解
浏览器的次要性能是将用户抉择的 web 资源出现进去,它须要从服务器申请资源,并将其显示在浏览器窗口中,资源的格局通常是 HTML,也包含 PDF、image 及其他格局。用户用 URI(Uniform Resource Identifier 对立资源标识符)来指定所申请资源的地位。
HTML 和 CSS 标准中规定了浏览器解释 html 文档的形式,由 W3C 组织对这些标准进行保护,W3C 是负责制订 web 规范的组织。然而浏览器厂商纷纷开发本人的扩大,对标准的遵循并不欠缺,这为 web 开发者带来了重大的兼容性问题。
浏览器能够分为两局部,shell 和 内核。其中 shell 的品种绝对比拟多,内核则比拟少。也有一些浏览器并不辨别外壳和内核。从 Mozilla 将 Gecko 独立进去后,才有了外壳和内核的明确划分。
- shell 是指浏览器的外壳:例如菜单,工具栏等。次要是提供给用户界面操作,参数设置等等。它是调用内核来实现各种性能的。
- 内核是浏览器的外围。内核是基于标记语言显示内容的程序或模块。
Promise.resolve
Promise.resolve = function(value) { // 1.如果 value 参数是一个 Promise 对象,则一成不变返回该对象 if(value instanceof Promise) return value; // 2.如果 value 参数是一个具备 then 办法的对象,则将这个对象转为 Promise 对象,并立刻执行它的then办法 if(typeof value === "object" && 'then' in value) { return new Promise((resolve, reject) => { value.then(resolve, reject); }); } // 3.否则返回一个新的 Promise 对象,状态为 fulfilled return new Promise(resolve => resolve(value));}
说一下JSON.stringify有什么毛病?
1.如果obj外面有工夫对象,则JSON.stringify后再JSON.parse的后果,工夫将只是字符串的模式,而不是对象的模式2.如果obj里有RegExp(正则表达式的缩写)、Error对象,则序列化的后果将只失去空对象;3、如果obj里有函数,undefined,则序列化的后果会把函数或 undefined失落;4、如果obj里有NaN、Infinity和-Infinity,则序列化的后果会变成null5、JSON.stringify()只能序列化对象的可枚举的自有属性,例如 如果obj中的对象是有构造函数生成的, 则应用JSON.parse(JSON.stringify(obj))深拷贝后,会抛弃对象的constructor;6、如果对象中存在循环援用的状况也无奈正确实现深拷贝;
对Promise的了解
Promise是异步编程的一种解决方案,它是一个对象,能够获取异步操作的音讯,他的呈现大大改善了异步编程的窘境,防止了天堂回调,它比传统的解决方案回调函数和事件更正当和更弱小。
所谓Promise,简略说就是一个容器,外面保留着某个将来才会完结的事件(通常是一个异步操作)的后果。从语法上说,Promise 是一个对象,从它能够获取异步操作的音讯。Promise 提供对立的 API,各种异步操作都能够用同样的办法进行解决。
(1)Promise的实例有三个状态:
- Pending(进行中)
- Resolved(已实现)
- Rejected(已回绝)
当把一件事件交给promise时,它的状态就是Pending,工作实现了状态就变成了Resolved、没有实现失败了就变成了Rejected。
(2)Promise的实例有两个过程:
- pending -> fulfilled : Resolved(已实现)
- pending -> rejected:Rejected(已回绝)
留神:一旦从进行状态变成为其余状态就永远不能更改状态了。
Promise的特点:
- 对象的状态不受外界影响。promise对象代表一个异步操作,有三种状态,
pending
(进行中)、fulfilled
(已胜利)、rejected
(已失败)。只有异步操作的后果,能够决定以后是哪一种状态,任何其余操作都无奈扭转这个状态,这也是promise这个名字的由来——“承诺”; - 一旦状态扭转就不会再变,任何时候都能够失去这个后果。promise对象的状态扭转,只有两种可能:从
pending
变为fulfilled
,从pending
变为rejected
。这时就称为resolved
(已定型)。如果扭转曾经产生了,你再对promise对象增加回调函数,也会立刻失去这个后果。这与事件(event)齐全不同,事件的特点是:如果你错过了它,再去监听是得不到后果的。
Promise的毛病:
- 无奈勾销Promise,一旦新建它就会立刻执行,无奈中途勾销。
- 如果不设置回调函数,Promise外部抛出的谬误,不会反馈到内部。
- 当处于pending状态时,无奈得悉目前停顿到哪一个阶段(刚刚开始还是行将实现)。
总结: Promise 对象是异步编程的一种解决方案,最早由社区提出。Promise 是一个构造函数,接管一个函数作为参数,返回一个 Promise 实例。一个 Promise 实例有三种状态,别离是pending、resolved 和 rejected,别离代表了进行中、已胜利和已失败。实例的状态只能由 pending 转变 resolved 或者rejected 状态,并且状态一经扭转,就凝固了,无奈再被扭转了。
状态的扭转是通过 resolve() 和 reject() 函数来实现的,能够在异步操作完结后调用这两个函数扭转 Promise 实例的状态,它的原型上定义了一个 then 办法,应用这个 then 办法能够为两个状态的扭转注册回调函数。这个回调函数属于微工作,会在本轮事件循环的开端执行。
留神: 在结构 Promise
的时候,构造函数外部的代码是立刻执行的
AJAX
实现:利用 XMLHttpRequest
// getconst getJSON = (url) => { return new Promise((resolve, reject) => { let xhr = new XMLHttpRequest(); // open 办法用于指定 HTTP 申请的参数: method, url, async(是否异步,默认true) xhr.open("GET", url, false); xhr.setRequestHeader('Content-Type', 'application/json'); // onreadystatechange 属性指向一个监听函数。 // readystatechange 事件产生时(实例的readyState属性变动),就会执行这个属性。 xhr.onreadystatechange = function(){ // 4 示意服务器返回的数据曾经齐全接管,或者本次接管曾经失败 if(xhr.readyState !== 4) return; // 申请胜利,基本上只有2xx和304的状态码,示意服务器返回是失常状态 if(xhr.status === 200 || xhr.status === 304) { // responseText 属性返回从服务器接管到的字符串 resolve(xhr.responseText); } // 申请失败 else { reject(new Error(xhr.responseText)); } } xhr.send(); });}// postconst postJSON = (url, data) => { return new Promise((resolve, reject) => { let xhr = new XMLHttpRequest(); xhr.open("POST", url); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.onreadystatechange = function(){ if(xhr.readyState !== 4) return; if(xhr.status === 200 || xhr.status === 304) { resolve(xhr.responseText); } else { reject(new Error(xhr.responseText)); } } xhr.send(data); });}
如何判断一个对象是不是空对象?
Object.keys(obj).length === 0
手写题:在线编程,getUrlParams(url,key); 就是很简略的获取url的某个参数的问题,但要思考边界状况,多个返回值等等
说一下vue3.0你理解多少?
<!-- 响应式原理的扭转 Vue3.x 应用Proxy取代 Vue2.x 版本的Object.defineProperty --> <!-- 组件选项申明形式Vue3.x 应用Composition API setup 是Vue3.x新增的一个选项,他 是组件内应用Composition API 的入口 --> <!-- 模板语法变动slot具名插槽语法 自定义指令 v-model 降级 --> <!-- 其它方面的更改Suspense反对Fragment(多个根节点) 和Protal (在dom其余局部渲染组建内容)组件 针对一些非凡的场景做了解决。基于treeshaking优化,提供了更多的内置性能。 -->
节流
节流(throttle
):触发高频事件,且 N 秒内只执行一次。这就好比公交车,10 分钟一趟,10 分钟内有多少人在公交站等我不论,10 分钟一到我就要发车走人!相似qq飞车的复位按钮。
核心思想:应用工夫戳或标记来实现,立刻执行一次,而后每 N 秒执行一次。如果N秒内触发则间接返回。
利用:节流常利用于鼠标一直点击触发、监听滚动事件。
实现:
// 版本一:标记实现function throttle(fn, wait){ let flag = true; // 设置一个标记 return function(...args){ if(!flag) return; flag = false; setTimeout(() => { fn.call(this, ...args); flag = true; }, wait); }}// 版本二:工夫戳实现function throttle(fn, wait) { let pre = 0; return function(...args) { let now = new Date(); if(now - pre < wait) return; pre = now; fn.call(this, ...args); }}
setTimeout 模仿 setInterval
形容:应用setTimeout
模仿实现setInterval
的性能。
实现:
const mySetInterval(fn, time) { let timer = null; const interval = () => { timer = setTimeout(() => { fn(); // time 工夫之后会执行真正的函数fn interval(); // 同时再次调用interval自身 }, time) } interval(); // 开始执行 // 返回用于敞开定时器的函数 return () => clearTimeout(timer);}// 测试const cancel = mySetInterval(() => console.log(1), 400);setTimeout(() => { cancel();}, 1000); // 打印两次1
CDN的应用场景
- 应用第三方的CDN服务:如果想要开源一些我的项目,能够应用第三方的CDN服务
- 应用CDN进行动态资源的缓存:将本人网站的动态资源放在CDN上,比方js、css、图片等。能够将整个我的项目放在CDN上,实现一键部署。
- 直播传送:直播实质上是应用流媒体进行传送,CDN也是反对流媒体传送的,所以直播齐全能够应用CDN来进步访问速度。CDN在解决流媒体的时候与解决一般动态文件有所不同,一般文件如果在边缘节点没有找到的话,就会去上一层接着寻找,然而流媒体自身数据量就十分大,如果应用回源的形式,必然会带来性能问题,所以流媒体个别采纳的都是被动推送的形式来进行。
深拷贝浅拷贝
浅拷贝:浅拷贝通过ES6新个性Object.assign()或者通过扩大运算法...来达到浅拷贝的目标,浅拷贝批改正本,不会影响原数据,但毛病是浅拷贝只能拷贝第一层的数据,且都是值类型数据,如果有援用型数据,批改正本会影响原数据。深拷贝:通过利用JSON.parse(JSON.stringify())来实现深拷贝的目标,但利用JSON拷贝也是有毛病的,当要拷贝的数据中含有undefined/function/symbol类型是无奈进行拷贝的,当然咱们想我的项目开发中须要深拷贝的数据个别不会含有以上三种类型,如有须要能够本人在封装一个函数来实现。
absolute与fixed共同点与不同点
共同点:
- 扭转行内元素的出现形式,将display置为inline-block
- 使元素脱离一般文档流,不再占据文档物理空间
- 笼罩非定位文档元素
不同点:
- abuselute与fixed的根元素不同,abuselute的根元素能够设置,fixed根元素是浏览器。
- 在有滚动条的页面中,absolute会跟着父元素进行挪动,fixed固定在页面的具体位置。
对Flex布局的了解及其应用场景
Flex是FlexibleBox的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。任何一个容器都能够指定为Flex布局。行内元素也能够应用Flex布局。留神,设为Flex布局当前,子元素的float、clear和vertical-align属性将生效。采纳Flex布局的元素,称为Flex容器(flex container),简称"容器"。它的所有子元素主动成为容器成员,称为Flex我的项目(flex item),简称"我的项目"。容器默认存在两根轴:程度的主轴(main axis)和垂直的穿插轴(cross axis),我的项目默认沿程度主轴排列。
以下6个属性设置在容器上:
- flex-direction属性决定主轴的方向(即我的项目的排列方向)。
- flex-wrap属性定义,如果一条轴线排不下,如何换行。
- flex-flow属性是flex-direction属性和flex-wrap属性的简写模式,默认值为row nowrap。
- justify-content属性定义了我的项目在主轴上的对齐形式。
- align-items属性定义我的项目在穿插轴上如何对齐。
- align-content属性定义了多根轴线的对齐形式。如果我的项目只有一根轴线,该属性不起作用。
以下6个属性设置在我的项目上:
- order属性定义我的项目的排列程序。数值越小,排列越靠前,默认为0。
- flex-grow属性定义我的项目的放大比例,默认为0,即如果存在残余空间,也不放大。
- flex-shrink属性定义了我的项目的放大比例,默认为1,即如果空间有余,该我的项目将放大。
- flex-basis属性定义了在调配多余空间之前,我的项目占据的主轴空间。浏览器依据这个属性,计算主轴是否有多余空间。它的默认值为auto,即我的项目的原本大小。
- flex属性是flex-grow,flex-shrink和flex-basis的简写,默认值为0 1 auto。
- align-self属性容许单个我的项目有与其余我的项目不一样的对齐形式,可笼罩align-items属性。默认值为auto,示意继承父元素的align-items属性,如果没有父元素,则等同于stretch。
简略来说: flex布局是CSS3新增的一种布局形式,能够通过将一个元素的display属性值设置为flex从而使它成为一个flex容器,它的所有子元素都会成为它的我的项目。一个容器默认有两条轴:一个是程度的主轴,一个是与主轴垂直的穿插轴。能够应用flex-direction来指定主轴的方向。能够应用justify-content来指定元素在主轴上的排列形式,应用align-items来指定元素在穿插轴上的排列形式。还能够应用flex-wrap来规定当一行排列不下时的换行形式。对于容器中的我的项目,能够应用order属性来指定我的项目的排列程序,还能够应用flex-grow来指定当排列空间有残余的时候,我的项目的放大比例,还能够应用flex-shrink来指定当排列空间有余时,我的项目的放大比例。
代码输入后果
function Foo(){ Foo.a = function(){ console.log(1); } this.a = function(){ console.log(2) }}Foo.prototype.a = function(){ console.log(3);}Foo.a = function(){ console.log(4);}Foo.a();let obj = new Foo();obj.a();Foo.a();
输入后果:4 2 1
解析:
- Foo.a() 这个是调用 Foo 函数的静态方法 a,尽管 Foo 中有优先级更高的属性办法 a,但 Foo 此时没有被调用,所以此时输入 Foo 的静态方法 a 的后果:4
- let obj = new Foo(); 应用了 new 办法调用了函数,返回了函数实例对象,此时 Foo 函数外部的属性办法初始化,原型链建设。
- obj.a() ; 调用 obj 实例上的办法 a,该实例上目前有两个 a 办法:一个是外部属性办法,另一个是原型上的办法。当这两者都存在时,首先查找 ownProperty ,如果没有才去原型链上找,所以调用实例上的 a 输入:2
- Foo.a() ; 依据第2步可知 Foo 函数外部的属性办法已初始化,笼罩了同名的静态方法,所以输入:1
对JSON的了解
JSON 是一种基于文本的轻量级的数据交换格局。它能够被任何的编程语言读取和作为数据格式来传递。
在我的项目开发中,应用 JSON 作为前后端数据交换的形式。在前端通过将一个合乎 JSON 格局的数据结构序列化为
JSON 字符串,而后将它传递到后端,后端通过 JSON 格局的字符串解析后生成对应的数据结构,以此来实现前后端数据的一个传递。
因为 JSON 的语法是基于 js 的,因而很容易将 JSON 和 js 中的对象弄混,然而应该留神的是 JSON 和 js 中的对象不是一回事,JSON 中对象格局更加严格,比如说在 JSON 中属性值不能为函数,不能呈现 NaN 这样的属性值等,因而大多数的 js 对象是不合乎 JSON 对象的格局的。
在 js 中提供了两个函数来实现 js 数据结构和 JSON 格局的转换解决,
- JSON.stringify 函数,通过传入一个合乎 JSON 格局的数据结构,将其转换为一个 JSON 字符串。如果传入的数据结构不合乎 JSON 格局,那么在序列化的时候会对这些值进行对应的非凡解决,使其符合规范。在前端向后端发送数据时,能够调用这个函数将数据对象转化为 JSON 格局的字符串。
- JSON.parse() 函数,这个函数用来将 JSON 格局的字符串转换为一个 js 数据结构,如果传入的字符串不是规范的 JSON 格局的字符串的话,将会抛出谬误。当从后端接管到 JSON 格局的字符串时,能够通过这个办法来将其解析为一个 js 数据结构,以此来进行数据的拜访。