原型链指向
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
p1.__proto__.constructor // Person
Person.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,则序列化的后果会变成 null
5、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
// get
const 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();});
}
// post
const 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 数据结构,以此来进行数据的拜访。