首页 > IT职业 > IT图书 > 【面试向】极简前端知识点(不断更新)
CS 客户端 / 服务器架构
BS 浏览器 / 服务器架构
将URL看作资源,URL 中用 名词 表示。各种操作通过不同的请求方式来识别。目的是 只看接口和请求方式就能知道这是干嘛的,比如
顺便知道一下,除了 GET,POST 外,还有 HEAD, PUT,PATCH,DELETE 等请求方式
GET /api/libraries/123/books?keyword=game&sort=price&limit=10&offset=0
含义就是:从一堆图书馆中,找到第 123 个图书馆的书,在书里查询所有关键词为 game ,以价格排序,从 0 开始的前 10 条数据
幂等:多次请求结果一样,比如一条更新的请求,将数值更新为 5,执行几次都是更新为 5;
非幂等:添加。原来有三条数据,随着添加操作,数据数也随之增加
项目中的一个查询请求(这里从 RESTful 的角度讲,不应该用 POST)

一次请求
目前总结的理解方式为:让你当前正在写的 html 的宽度等于设备宽度
无法添加属性,但对于非基本类型(Array,Object)的属性依旧可以添加。
彻底冻结一个对象(一冻到底)
var obj = { arr: [1, 2]
}function freezen(obj) { Object.freeze(obj); Object.keys(obj).forEach(function(it, i) { if(typeof obj[it] === 'object') {
freezen(obj[it])
}
})
}
freezen(obj)
Array.from(likeArr)
[...likeArr]
Array.prototype.slice.call()
for 循环条件中 var 声明的变量等同于全局变量
for 循环条件中 let 声明的变量不是全局变量(全局中取不到),算作是 for 循环 {} 的 父级变量,不会影响 {} 中 let 声明同样的变量;这一点跟函数不一样,参数声明了 x ,函数体中需要注意 暂时性死区
var 声明的全局变量是 window 对象的一个属性,但 let 声明的对象不是
# map数组.map(function(值,下标,数组) {
console.log(arguments)
})# foreach数组.foreach(function(值,下标,数组) {
console.log(arguments)
})# $.each(jQuery)$.each(任何可遍历的对象, function(key, value) {
console.log(arguments)
})# each(jQuery)DOM对象.each(function(key, value) {
console.log(arguments)
})
箭头函数没有自己的 this,arguments,super,由于没有自己的 this,也就不能使用 bind,call,apply 更改 this 的指向,但不代表箭头函数不能调用那三个方法;
let obj = { name:'lky'
} let arrFn = () => { console.log(this);
} function commonFn(){ console.log(this)
}
arrFn(); // window
arrFn.call(obj); // window (可以调用,但没法改变 this 指向)
commonFn(); // window
commonFn.call(obj); // obj
箭头函数体只有一条语句时自带 return,且 return 可省略
提高性能,有牌面
祖先.addEventListener('click', function(e){ var target = e.target || e.srcElement; if (!!target && target.nodeName.toLowerCase()==='目标元素') { console.log(target.innerHTML)
}
})
[] 和 . 的区别[] 可以用变量,数字和保留字获取属性,ES6 还允许表达式
Object.assign(目标对象,源...)
合并 可枚举 的 自身 属性
浅拷贝,即引用时源改变了则目标也改变
Object.defineProperty(目标对象,属性名,{属性描述})
Object.defineProperty(obj, "key", { enumerable: false, configurable: false, writable: false, value: "static"});
Object.defineProperties(目标对象,属性组及属性描述)
var obj = {};Object.defineProperties(obj, { 'property1': { value: true, writable: true
}, 'property2': { value: 'Hello', writable: false
} // etc. etc.});
目标对象.hasOwnProperty(目标属性) obj 自身 是否含有目标属性,不是原型上,返回布尔值
Object.getPrototypeOf(目标对象) 获取目标对象的原型
Object.setPrototypeOf(目标对象,对象原型) 设置目标对象的原型
Object.create(新对象的原型,{新对象的属性:{属性描述}})(后者可选)
# 创建新对象 clone,其原型为 obj 的原型,添加 newProp 属性const obj = { 'a': 'aa',
222: 3123, 'unenumerable': '不可枚举属性'}
const clone = Object.create(Object.getPrototypeOf(obj), { 'newProp': {
value: '新值',
enumerable: true
}
});
Object.getOwnPropertyDescriptors(clone)
// newProp:{value: undefined, writable: false, enumerable: true, configurable: false}
// 未指定的属性均为 false
也可以:
const obj = { 'a': 'aa', 222: 3123, 'unenumerable': '不可枚举属性'}Object.defineProperty(obj, 'unenumerable', { enumerable: false})const clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj)
);Object.getOwnPropertyDescriptors(clone)
结果:

结果
这样就等同于 浅克隆 了一个 obj 对象 clone
Object.getOwnPropertyDescriptor(目标对象,目标对象属性) 获取目标对象自身的属性描述
const obj = { 'a': 'aa',
222: 3123
}
Object.getOwnPropertyDescriptor(obj, 'a')
// {value: "aa", writable: true, enumerable: true, configurable: true}
Object.getOwnPropertyDescriptors(目标对象) 获取目标对象自身的全部属性描述
const obj = { 'a': 'aa',
222: 3123, 'unenumerable':'不可枚举'}
Object.defineProperty(obj,'unenumerable',{enumerable:false}) // 设置为不可枚举
Object.getOwnPropertyDescriptors(obj)
/**
* 222: {value: 3123, writable: true, enumerable: true, configurable: true}
* a: {value: "aa", writable: true, enumerable: true, configurable: true}
* unenumerable: {value: "不可枚举", writable: true, enumerable: false, configurable: true}
**/
for ... in 自身及继承 的所有 可枚举 属性,不含 Symbol
Object.keys 返回数组,自身 所有 可枚举 属性(不含 Symbol 属性)的键名
Object.getOwnPropertyNames(obj) 自身,可枚举 及 不可枚举 的属性名(不含 Symbol)
| 名称 | 目标 | 类别 |
|---|---|---|
| for...in... | 自身及继承的属性名或索引 | 可枚举 |
| Object.keys | 自身 | 可枚举 |
| Object.values | 自身 | 可枚举 |
| Object.entries | 自身 | 可枚举 |
| Object.getOwnPropertyNames(obj) | 自身 | 可枚举 / 不可枚举 |
for ... of ...:遍历具有 Symbol.iterator 接口对象自身具有数字索引的值
for ... in ...:遍历对象自身及原型上可枚举的属性名或索引
let arr = [3, 5, 7];
arr.foo = 'hello';
Array.prototype.baz='world';for (let i in arr) {
console.log(i); // "0", "1", "2", "foo", "baz"}for (let i of arr) {
console.log(i); // "3", "5", "7"}
Set:没有重复值的 Array
Map:常规的 Object 是key:value形式,Map 支持 Object 等作为 key
渲染引擎遇到
// module_test.jslet delay = +new Date();
console.log('外部脚本');while(+new Date() - delay
// 结果外部脚本
---- 3s later ----
本地脚本
区别:

区别
| 类别 | 解释 |
|---|---|
| script | 解析 HTML - 下载 script - 解析 script - 继续解析 HTML |
| defer | 解析 HTML - 下载 script - 继续解析 HTML - 解析 script |
| async | 解析 HTML - 下载 script(此时仍在解析 HTML) - 解析 script - 解析 HTML |
jQuery.noConflict()
var j = jQuery.noConflict();// 基于 jQuery 的代码j("div p").hide();// 基于其他库的 $() 代码$("content").style.display = 'none';
方法加在 jQuery 上,然后通过
window.jQuery = window.$ = jQuery
数组操作
| 名称 | 用法 | 返回 |
|---|---|---|
| concat() | arrayObject.concat(arrayX,arrayX,......,arrayX) | 新数组 |
| join() | arrayObject.join(分隔符) | 字符串 |
| pop() | arrayObject.pop() | 最后一个元素 |
| push() | arrayObject.push(newelement1,newelement2,....,newelementX) | 添加后的长度 |
| reverse() | arrayObject.reverse() | 改变原数组 |
| shift() | arrayObject.shift() | 第一个元素 |
| slice() | arrayObject.slice(start,end) | 不改变原数组,返回新数组,支持负数 |
| sort() | arrayObject.sort(function) | 改变原数组 |
| splice() | arrayObject.splice(index,howmany,item1,.....,itemX) | 改变原数组 |
字符串操作
| 名称 | 描述 | 返回 |
|---|---|---|
| charAt() | 返回在指定位置的字符 | |
| concat() | 连接字符串 | |
| indexOf() | 检索字符串 | 布尔值 |
| match() | 找到一个或多个正则表达式的匹配 | 布尔值 |
| replace() | 替换与正则表达式匹配的子串 | 新字符串 |
| search() | 检索与正则表达式相匹配的值 | 第一个匹配子串的起始位置 |
| slice() | 提取字符串的片断,并在新的字符串中返回被提取的部分 | |
| split() | 把字符串分割为字符串数组 | |
| substr() | 从起始索引号提取字符串中 指定数目 的字符 | |
| substring() | 提取字符串中两个 指定的索引号 之间的字符 |
回流:更改了 DOM 结构(display:none),回流也会触发重绘
重绘:变个颜色,加个边框之类的

cellpadding 和 cellspacing
Array.isArray()
或
Object.prototype.toString.call()==='[object Object]'Object.prototype.toString.call()==='[object Array]'Object.prototype.toString.call()==='[object Set]'Object.prototype.toString.call()==='[object Map]'Object.prototype.toString.call()==='[object Symbol]'Object.prototype.toString.call()==='[object String]'Object.prototype.toString.call()==='[object Null]'Object.prototype.toString.call()==='[object Undefined]' Object.prototype.toString.call()==='[object Boolean]'Object.prototype.toString.call()==='[object Number]'
判断 NaN 用 isNaN(),或者 Object.is()
| 区别 | === | Object |
|---|---|---|
| +0,-0 | true | false |
| NaN,NaN | false | true |
get
var xhr = new XMLHttpRequest();
xhr.open('get','getStar.php?starName='+name,true);
xhr.send();
xhr.onreadystatechange = function () { if (xhr.readyState==4 && xhr.status==200) {
console.log(xhr.responseText); //输入相应的内容
}
}
post
var xhr = new XMLHttpRequest();
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.open('post', '02.post.php' ,true);
xhr.send('name=fox&age=18');
xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200) { console.log(xhr.responseText);
}
};
工厂模式:无法判断对象类型(对比构造函数模式)
function createPerson(){ var Child = new Object();
Child.name = "欲泪成雪";
Child.age = "20"; return Child;
};var x = createPerson();
构造函数模式:可以通过 x instanceof Person 得知 x 是 Person,而工厂模式则无法知道 x 是 Person;
function Person(){ this.name = "欲泪成雪"; this.age = "20"; this.say = function(){
alert("Hello!")
}
};function Fruit(){ this.name = "水果"; this.price = "13";
};var x = new Person();var y = new Fruit();
但这种模式每次实例化都会重新初始化属性 arr 和方法 say ,并且不同实例的 arr 和 say 并不是一个玩意
function Person() { this.name = "欲泪成雪"; this.age = "20"; this.arr = [0,1]; this.say = function(){
alert("Hello")
}
};var Tom = new Person();var Jerry = new Person();console.log(Tom.name === Jerry.name) // trueconsole.log(Tom.arr === Jerry.arr) // falseconsole.log(Tom.say === Jerry.say) // false
原型模式:如下这种形式,每个实例的属性和方法都相同
function Person(){};Parent.prototype.name = "欲泪成雪";Parent.prototype.age = "20";var x = new Person();
混合模式(构造 + 原型)
function Person(){
this.name = "欲泪成雪";
this.age = 22;
};
Person.prototype.lev = function(){
return this.name;
};var x = new Person();
| get | post |
|---|---|
| URL中发送 | 消息主体 |
| 可缓存 | 不可缓存 |
| 可历史记录 | 不可保留为历史记录 |
| 可书签 | 不可书签 |
| 有长度限制 | 没有长度限制 |
querySelectorAll 可直接放选择器 '.abc'
querySelectorAll 性能不如前者
querySelectorAll 静态查找
新增选择器 document.querySelector、document.querySelectorAll
拖拽释放(Drag and drop) API
媒体播放的 video 和 audio
本地存储 localStorage 和 sessionStorage
离线应用 manifest
桌面通知 Notifications
语意化标签 article、footer、header、nav、section
增强表单控件 calendar、date、time、email、url、search
地理位置 Geolocation
多任务 webworker
全双工通信协议 websocket
历史管理 history
跨域资源共享(CORS) Access-Control-Allow-Origin
页面可见性改变事件 visibilitychange
跨窗口通信 PostMessage
Form Data 对象
绘画 canvas
CSS3
@media screen and (min-width:960px) and (max-width:1200px){ body{background:yellow;}
}
也可以这样
function Foo(){}
Foo.prototype = { css:function(){ console.log("设置css样式"); return this;
}, show:function(){ console.log("将元素显示"); return this;
}, hide:function(){ console.log("将元素隐藏");
}
};var foo = new Foo();
foo.css().css().show().hide();
关键词:容器,项目,主轴,交叉轴
容器和项目是父子集
容器 display:flex 后,float,clear,vertical-align 失效
容器
| 属性名 | 描述 |
|---|---|
| flex-direction | 主轴的方向 |
| flex-wrap | 如何换行 |
| flex-flow | 上两个的缩写 |
| justify-content | 项目在主轴的对齐方式 |
| align-items | 项目在交叉轴的对齐方式 |
项目
| 属性名 | 描述 |
|---|---|
| order | 项目排列顺序,越小越靠前 |
| flex-grow | 项目放大比例 |
| flex-shrink | 项目缩小比例 |
| flex-basis | 属性定义了在分配多余空间之前,项目占据的主轴空间 |
| flex | 上三个的缩写 |
| align-self | 项目在交叉轴上的对齐方式 |
兼容

flex 兼容
直接操作 DOM 成本高,通过 JavaScript 创建一个记录 DOM 的对象,之后一次渲染这个对象
先定义一个构造函数
//虚拟dom,参数分别为标签名、属性对象、子DOM列表var VElement = function(tagName, props, children) { //保证只能通过如下方式调用:new VElement
if (!(this instanceof VElement)) { return new VElement(tagName, props, children);
} //可以通过只传递tagName和children参数
if (util.isArray(props)) {
children = props;
props = {};
} //设置虚拟dom的相关属性
this.tagName = tagName; this.props = props || {}; this.children = children || []; this.key = props ? props.key : void 666; var count = 0;
util.each(this.children, function(child, i) { if (child instanceof VElement) {
count += child.count;
} else {
children[i] = '' + child;
}
count++;
}); this.count = count;
}
生成实例,用 JavaScript 表示 DOM 结构
var vdom = velement('div', { 'id': 'container' }, [
velement('h1', { style: 'color:red' }, ['simple virtual dom']),
velement('p', ['hello world']),
velement('ul', [velement('li', ['item #1']), velement('li', ['item #2'])]),
]);
上面的 JavaScript 代码就代表了如下的 DOM 结构
simple virtual dom
hello world
- item #1
- item #2
computed 可以新建一个属性
watch 只能用 data 中已有的属性
{{ fullName }}// watchvar vm = new Vue({ el: '#demo', data: { firstName: 'Foo', lastName: 'Bar', fullName: 'Foo Bar' }, watch: { firstName: function (val) { // firstName 和 lastName 都是 data 中已有的属性 this.fullName = val + ' ' + this.lastName }, lastName: function (val) { this.fullName = this.firstName + ' ' + val } } })// computedvar vm = new Vue({ el: '#demo', data: { firstName: 'Foo', lastName: 'Bar' }, computed: { fullName: function () { // fullName 在 data 中并没有 return this.firstName + ' ' + this.lastName } } })
父子集关系:
1.父级 overflow:hidden
2.父级添加 border
3.父级添加 padding
兄弟集关系:
1.任意兄弟添加 display:inline-block
2.下面的添加 float:left

图片下小空白
红框为父级 图片设置: 父级设置: 父子同时设置: 修改 span 的 vertical-align 可以理解为定义一个环境,在这个环境内的元素不论怎么调整都不会影响环境外部的样式 形成条件 公有方法:实例可以调用 私有方法:只能在构造函数内调用,一般用于对构造函数内的属性或方法进行修改 静态属性:只能由构造函数自己调用,而不能被实例调用的属性 数据属性: 访问器属性: 这个思路跟上一个很像,所以放在一起 generator 版 一直以来我都认为这种题意义不大,然而每次遇到这种题时却发现答案总是摇摆不定,归根结底还是基础不够扎实,因此只好强忍着恶心再来一点点分析 这个也得改一下,先是把函数改成这样: 而调用 这题主要是变量提升,与下面这种写法是等价的,再看不懂就去面壁 三个的 也是先把变量提升处理了,改成下面这种,注意:同样是声明提升,但变量提升在函数声明之上 第一个 第二个打印可改成如下, 因为调用 结果 分析: JavaScript 采用词法作用域(静态作用域),函数的作用域在定义时已经确定, 函数定义时确定作用域,函数调用时先创建执行上下文,在具体的执行过程中再进行执行上下文初始化 1.创建一个新对象 ABC 收藏了某店铺,店铺更新商品时,ABC 就会收到通知。ABC 就是订阅者,店铺就是发布者 父级高度不固定,即内容撑开父级时:为父级添加 padding 即可 父级高度固定(IE8 及以上有效):
啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦 伪类: 伪元素: 通过伪元素添加的 矢量图是伪元素的 content BOM & DOM 实例化 MVVM 的过程中做了以下三件事: 2. 实例化 Observer ,用于重写 options.data 所有属性的访问器属性,即 get 和 set 方法,重写的目的是: 虚拟DOM 手机号:以 1 开头,第二位是 3~8 中的一个,之后是 9 个 0~9 结尾 日期匹配:前四位是数字,接着是 邮箱:第一位是数字字母下划线 + 数字字母下划线横线任意个 + @ + 数字字母至少一个 + (点 + 至少一个字母)至少一组结尾 练习:匹配 不使用 return 包裹的数据会在项目的全局可见,会造成变量污染 使用return 包裹后数据中变量只在当前组件中生效,不会影响其他组件。 oninput:输入框内容变了就触发 onchange:输入框内容变化并失去焦点时触发 父 子: 父调用子方法 link 属于 html 标签,而 @import 是 css 提供的。 页面被加载时,link会同时被加载,而 @import 引用的 css 会等到页面加载结束后加载。 link 是 html 标签,因此没有兼容性,而 @import 只有 IE5 以上才能识别。 link 方式样式的权重高于 @import 列表不同颜色 效果 不同浏览器内外边距不同 部分浏览器 苹果浏览器不支持 为不同浏览器的 baseline 对齐,基线就是 xxx 的下边界,因此修改图片的对齐方式 vertical-align 即可
1.display:block
2.vertical-align:top
1.font-size:0
1.float:left
BFC 是什么?
1.浮动元素,float 除 none 以外的值;
2.绝对定位元素,position(absolute,fixed);
3.display 为以下其中之一的值 inline-blocks,table-cells,table-captions;
4.overflow 除了 visible 以外的值(hidden,auto,scroll)
公有方法,私有方法,静态属性
function Foo(){ // 公有方法
this.name = function(){
alert("Hello")
} // 私有方法
function age(){
alert("World")
}
}
# ES5function Foo(){}
Foo.age = 12; // 静态属性Foo.getAge = function(){ // 静态方法
console.log(this.age)
}# ES6 class Foo{ static age(){ // 静态方法
console.log(12)
}
}
Foo.sex = 'boy' // 静态属性(ES6 类内没有静态属性)
ES6 继承
class Son extends Dad {}
数据属性 / 访问器属性
1.configurable
2.enumerable
3.writable
4.value
1.configurable
2.enumerable
3.get
4.set
实现一个深拷贝
function deepClone(obj) { var newObj = obj instanceof Array ? [] : {}; //obj属于基本数据类型,直接返回obj
if(typeof obj !== 'object') { return obj;
} else { //obj属于数组或对象,遍历它们
for(var i in obj) {
newObj[i] = typeof obj[i] === 'object' ? deepClone(obj[i]):obj[i];
}
} return newObj;
}
取出嵌套数组的全部数值
// 常规版let newArr = [];function getArr(arr) { for(let i = 0; i
const arr = ["a", "b", "c", "d", ["aa", "bb"]];function* tree(item) { if(Array.isArray(item)) { // 如果是数组,就依次取出,再调用自己
for(var i = 0; i
克隆对象及原型链
// 写法一const clone1 = Object.assign( Object.create(Object.getPrototypeOf(obj)),
obj
);// 写法二const clone2 = Object.create( Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj)
)
几道面试题
function create(obj){
obj.name = '粉粉';
obj = new Object();
obj.name = '娇娇';
}var person = new Object();
create(person);console.log(person.name); // 粉粉
function create() { var obj;
obj.name = '粉粉';
obj = new Object();
obj.name = '娇娇';
}
create(person) 变成这样:function create() { var obj = person; // 此时 obj 和 person 指向一块内存
obj.name = '粉粉'; // 为同一块内存添加属性,这是 obj 和 person 共有的属性
obj = new Object(); // 然后让 obj 指向另一块内存
obj.name = '娇娇'; // obj 已经指向另一块内存,再为 obj 添加属性当然跟 person 无关了}
var a = '小旭';
(function(){ console.log(typeof a) // undefined
console.log(typeof fun1) // function
console.log(typeof fun2) // undefined
var a = '旭旭'; function fun1(){}; var fun2 = function(){} console.log(typeof a); // string
console.log(typeof fun1); // function
console.log(typeof fun2); // function})(window)
var a = '小旭';
(function(){ var a; function fun1(){}; var fun2; console.log(typeof a) // undefined
console.log(typeof fun1) // function
console.log(typeof fun2) // undefined
a = '旭旭';
fun2 = function(){} console.log(typeof a); // string
console.log(typeof fun1); // function
console.log(typeof fun2); // function})(window)
var foo = { bar:function(){ return this.baz;
}, baz:1};
(function(){ console.log(arguments[0]()); // undefined
console.log(foo.bar()); // 1
console.log(arguments[0].call(foo)); // 1})(foo.bar)
this 分别指向 arguments,foo,foo
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(); // 2getName(); // 4Foo().getName(); // 1getName(); // 1new Foo.getName(); // 2new Foo().getName(); // 3
1.打印静态方法,没啥说的
2.全局的 getName 一共赋了三次值(两次在全局赋值,一次在局部赋值),第一次:function getName(){console.log(5);},第二次:function getName();{console.log(4);};第三次为局部赋值:function Foo(){ getName = function(){console.log(1);} return this; }
3.Foo() 构造函数也可以当做普通函数调用, Foo() 调用后,内部又对全局的 getName 重新赋值为 function(){console.log(1);} 返回的 this 指向 window,相当于调用 window.getName(),而此时的 getName() 在调用 Foo() 后已被赋值为 1
4.window.getName() 就等于在全局直接调用 getName()
5.不要想太多,反正 Foo.getName 就是个普通函数,把 Foo.getName 看做 abc 就完了,这里只是实例化的过程中伴随了执行的操作罢了
6.相当于 实例.getName(),调用的是原型上的方法 Foo.prototype.getName = function(){console.log(3);}var getName;function Foo(){
getName = function(){console.log(1);} return this;
}function getName(){console.log(5);}
Foo.getName = function(){console.log(2);}
Foo.prototype.getName = function(){console.log(3);}
getName = function(){console.log(4);}
Foo.getName(); // 2getName(); // 4Foo().getName(); // 1getName(); // 1new Foo.getName(); // 2new Foo().getName(); // 3
var fullName = 'language';var obj = { fullName:'javascript', prop:{ getFullName:function(){ return this.fullName;
}
}
}console.log(obj.prop.getFullName()); // undefinedvar test = obj.prop.getFullName;console.log(test()); // language
this 指向的是 obj.propthis 指向 windowvar fullName = 'language';var obj = { fullName:'javascript', prop:{ getFullName:function(){ return this.fullName;
}
}
}console.log(obj.prop.getFullName()); // undefinedvar test = function(){ return this.fullName
}console.log(test());
var name = 'Jerry';var Tom = { name:'Tom', show:function(){ console.log(this.name)
}, wait:function(){ var fun = this.show;
fun();
}
};
Tom.wait(); // Jerry
Tom.wait() 时,this 指向 Tom,因此 wait 属性中的 this.show 实际上就是 Tom.show,那就可以改成下面这种:var name = 'Jerry';var Tom = { name:'Tom', show:function(){ console.log(this.name)
}, wait:function(){ function fun(){ console.log(this.name) // 这里的 this 指向 window
}
fun();
}
};
Tom.wait(); // Jerry
setTimeout(function() { // 定时器1
var end = +new Date(); console.log(end - start)
}, 1000)
setTimeout(function() { // 定时器2
console.log('哈哈哈')
}, 0)console.time('circle')let delay = +new Date();while(+new Date() - delay

1.想像任务队列是个时间轴
2.定时器1:异步任务,放到任务队列 1000ms 的时间点上。
3.定时器2:异步任务,放到任务队列 0ms 的时间点上
4.同步阻塞 1500ms ,此时,定时器1 的任务也已经从 1000ms 的时间点移至紧随 定时器2 的时间点,也就是说,此时如果 定时器2 执行,定时器1 也将紧随其后执行,不需再等待 1000ms。
5.执行同步任务 var start = +new Date();执行完后,执行栈已空,可以开始执行任务队列中的任务,先执行定时器2,然后 立刻 执行定时器1
var value = 1;function foo() { console.log(value);
}function bar() { var value = 2;
foo();
}
bar(); // 1
foo 的定义时的 value 为全局变量
实现 bind 方法
bind / call 的区别
bind 返回函数,call 立即调用var obj = { name : 24}function fn(){ console.log(this.name);
}
fn.bind(obj)() // 24fn.call(obj) // 24
new 操作符做了什么
2.将构造函数的 this 指向新对象
3.执行构造函数
4.返回新对象function Foo(){ this.name = '我亦飘零';
};var obj = {};
obj.__proto__ = Foo.prototype;
Foo.call(obj)
函数柯里化
常见的浏览器兼容问题 js / css
* png24位的图片在iE6浏览器上出现背景,解决方案是做成PNG8.也可以引用一段脚本处理.
* 浏览器默认的margin和padding不同。解决方案是加一个全局的*{margin:0;padding:0;}来统一。
* IE6双边距bug:块属性标签float后,又有横行的margin情况下,在ie6显示margin比设置的大。
* 浮动ie产生的双倍距离(IE6双边距问题:在IE6下,如果对元素设置了浮动,同时又设置了margin-left或margin-right,margin值会加倍。) #box{ float:left; width:10px; margin:0 0 0 100px;}
这种情况之下IE会产生20px的距离,解决方案是在float的标签样式控制中加入 ——_display:inline;将其转化为行内属性。(_这个符号只有ie6会识别)
* 渐进识别的方式,从总体中逐渐排除局部。
首先,巧妙的使用“9”这一标记,将IE游览器从所有情况中分离出来。
接着,再次使用“+”将IE8和IE7、IE6分离开来,这样IE8已经独立识别。
css
.bb{
background-color:#f1ee18;/*所有识别*/
.background-color:#00deff9; /*IE6、7、8识别*/
+background-color:#a200ff;/*IE6、7识别*/
_background-color:#1e0bd1;/*IE6识别*/
}
* IE下,可以使用获取常规属性的方法来获取自定义属性,
也可以使用getAttribute()获取自定义属性;
Firefox下,只能使用getAttribute()获取自定义属性.
解决方法:统一通过getAttribute()获取自定义属性.
* IE下,event对象有x,y属性,但是没有pageX,pageY属性;
Firefox下,event对象有pageX,pageY属性,但是没有x,y属性.
* 解决方法:(条件注释)缺点是在IE浏览器下可能会增加额外的HTTP请求数。
* Chrome 中文界面下默认会将小于 12px 的文本强制按照 12px 显示,
可通过加入 CSS 属性 -webkit-text-size-adjust: none; 解决.
* 超链接访问过后hover样式就不出现了 被点击访问过的超链接样式不在具有hover和active了解决方法是改变CSS属性的排列顺序:
L-V-H-A : a:link {} a:visited {} a:hover {} a:active {}
* 怪异模式问题:漏写DTD声明,Firefox仍然会按照标准模式来解析网页,但在IE中会触发怪异模式。为避免怪异模式给我们带来不必要的麻烦,最好养成书写DTD声明的好习惯。现在可以使用[html5](http://www.w3.org/TR/html5/single-page.html)推荐的写法:`
常用的自适应解决方案
cookie,localStorage,sessionStorage 差异及使用场景
发布 - 订阅模式
多行文本垂直居中
1.父级添加:display:table;
2.子集添加:display:table-cell; vertical-align:middle// css
div {
height:500px;
width:300px;
border:1px solid red;
font-size: 30px;
display: table;
}
p {
display: table-cell;
vertical-align: middle;
}
// html
未知大小图片水平垂直居中
标签外套一层 标签a{display:inline-block; width:1.2em; font-size:128px; text-align:center; vertical-align:middle;}img{vertical-align:middle;}
溢出显示省略号
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
伪类 / 伪元素
属性
描述
CSS
:active
向被激活的元素添加样式。
1
:focus
向拥有键盘输入焦点的元素添加样式。
2
:hover
当鼠标悬浮在元素上方时,向元素添加样式。
1
:link
向未被访问的链接添加样式。
1
:visited
向已被访问的链接添加样式。
1
:first-child
向元素的第一个子元素添加样式。
2
:lang
向带有指定 lang 属性的元素添加样式。
2
属性
描述
CSS
:first-letter
向文本的第一个字母添加特殊样式。
1
:first-line
向文本的首行添加特殊样式。
1
:before
在元素之前添加内容。
2
:after
在元素之后添加内容。
2
去掉 ul 前面的点
list-style:none
引用的阿里矢量图为什么能改颜色
content 内容,属于文本
BOM

关于 Vue 双向绑定 和 虚拟DOM
1. 传入一个 options 配置对象,类似这种,MVVM 的参数就是: var vm = new MVVM({ el: '#mvvm-app', data: { someStr: 'hello ', className: 'btn', htmlStr: 'red', child: { someStr: 'World !'
}
}, computed: { getHelloWord: function() { return this.someStr + this.child.someStr;
}
}, methods: { clickBtn: function(e) { var randomStrArr = ['childOne', 'childTwo', 'childThree']; this.child.someStr = randomStrArr[parseInt(Math.random() * 3)];
}
}
});
a. 通过重写的 get 实现:哪里读取数据,就把哪里当做一个 Watcher,并将它存到 dep.subs 中
b. 通过重写的 set 实现:修改 data 数据时调用 notice() 通知所有观察者进行更新 update()
3. 实例化 Compile , 用于编译 options.el ,效果是:
a. 找出 options.el 中引用到 options.data 的部分,每找到一处就实例化一个观察者 Watcher,而 Watcher 本身定义有一个 update() 方法
b. 初始化渲染,初始化时会读取 options.data 的数据用于渲染视图,也就将所有 Watcher 存入了 dep.subs
将 #mvvm-app 内的节点存为一个 文档片段,通过判断模板 {{}} 和各种 v- 指令,将 data 信息写到 文档片段 上,最后将 文档片段 一次插入 #mvvm-app 中
几个常用的正则
/^1[34578][0-9]{9}$/
/ 和 - 中的一个,然后两个数字,接着是 / 和 - 中的一个,然后两个数字结尾/^d{4}[/-]d{2}[/-]d{2}$/// 1983-12-27// 1983/12/16
/^[a-zA-Z0-9_][a-zA-Z0-9_-]*@[a-zA-Z0-9]+(.[a-zA-Z]+)+$/
aabc222babc222bbabc 中的字母部分/((a)|(b{1,2}))abc/g
Vue 中 data 为什么使用 return
Vue 中使用 data 中的一个数组属性渲染页面,修改数组属性时,页面是否响应
oninput / onchange
Vue 组件通信
1.prop
2.子组件调用 this.$parent
3.provide / inject
1.ref
link 和 @import
SCSS
1.$ 定义变量
2.@each ... in ... 列表循环
3.index(list,item) 内置方法,返回下标
4.#{} 插值
5.nth(list,idx) 内置方法,返回值
// html
浏览器兼容
ie9 以下不支持 HTML5 标签和媒体查询:使用 html5shiv.js 和 respone.js 标签之间有间隔:给 浮动ie9 以下不支持 opacity:filter:alpha(opacity=50)cursor:hand。统一用 cursor:pointerCSS 前缀:profixfree.jsie8:不支持 placeholder,用 onfocus 和 onblur 模拟,并且需要手动添加 value;或者用 placeholder.jsie8:不支持 里面有 、 等元素的跳转。ie8 圆角:在 css 中引入 behavior:PIE.htc
flexible.js
750 的设计稿,flexible.js 将其分为 100 份,每 10 份为 1rem,因此 1rem = 750 / 10 = 75px750 的设计稿上有个宽 195 的图片,我们需要写的 rem 值为 195 / 75 = 2.6 rem
判断设备
window.navigator.userAgent// chrome"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36"// firefox"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0"// IE8"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E)"// IE7"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E)"// iPhone 5/SE 320*568"Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1"// iPhone 6/7/8 375*667"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1"// Galaxy S5 360*640"Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Mobile Safari/537.36"
MVVM
作者:_我亦飘零
链接:https://www.jianshu.com/p/c4e9684716f3
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/2310/viewspace-2803449/ ,如需转载,请注明出处,否则将追究法律责任。