this指向:
https://www.cnblogs.com/rinack/p/5698018.html
冒泡:
1.event.stopPropagation();
事件处理过程中,阻止了事件冒泡,但不会阻击默认行为(它就执行了超链接的跳转)
2.return false;
事件处理过程中,阻止了事件冒泡,也阻止了默认行为(比如刚才它就没有执行超链接的跳转)
还有一种有冒泡有关的:
3.event.preventDefault();
如果把它放在头部A标签的click事件中,点击“点击我”。
会发现它依次弹出:我是最里层---->我是中间层---->我是最外层,但最后却没有跳转到百度
它的作用是:事件处理过程中,不阻击事件冒泡,但阻击默认行为(它只执行所有弹框,却没有执行超链接跳转)
创建对象:
1.new 对象
var person = new Object();
person.name = "lisi";
person.age = 21;
person.family = ["lida","lier","wangwu"];
person.say = function(){
alert(this.name);
}
2.直接创建
var person ={
name: "lisi",
age: 21,
family: ["lida","lier","wangwu"],
say: function(){
alert(this.name);
}
};
3.工厂模式
function createPerson(name,age,family) {
var o = new Object();
o.name = name;
o.age = age;
o.family = family;
o.say = function(){
alert(this.name);
}
return o;
}
var person1 = createPerson("lisi",21,["lida","lier","wangwu"]); //instanceof无法判断它是谁的实例,只能判断他是对象,构造函数都可以判断出
var person2 = createPerson("wangwu",18,["lida","lier","lisi"]);
console.log(person1 instanceof Object); //true
4.构造函数
function Person(name,age,family) {
this.name = name;
this.age = age;
this.family = family;
this.say = function(){
alert(this.name);
}
}
var person1 = new Person("lisi",21,["lida","lier","wangwu"]);
var person2 = new Person("lisi",21,["lida","lier","lisi"]);
console.log(person1 instanceof Object); //true
console.log(person1 instanceof Person); //true
console.log(person2 instanceof Object); //true
console.log(person2 instanceof Person); //true
console.log(person1.constructor); //constructor 属性返回对创建此对象的数组、函数的引用
5.原型模式
function Person() {
}
Person.prototype.name = "lisi";
Person.prototype.age = 21;
Person.prototype.family = ["lida","lier","wangwu"];
Person.prototype.say = function(){
alert(this.name);
};
console.log(Person.prototype); //Object{name: 'lisi', age: 21, family: Array[3]}
var person1 = new Person(); //创建一个实例person1
console.log(person1.name); //lisi
var person2 = new Person(); //创建实例person2
person2.name = "wangwu";
person2.family = ["lida","lier","lisi"];
console.log(person2); //Person {name: "wangwu", family: Array[3]}
// console.log(person2.prototype.name); //报错
console.log(person2.age); //21
6.混合模式
function Person(name,age,family){
this.name = name;
this.age = age;
this.family = family;
}
Person.prototype = {
constructor: Person, //每个函数都有prototype属性,指向该函数原型对象,原型对象都有constructor属性,这是一个指向prototype属性所在函数的指针
say: function(){
alert(this.name);
}
}
var person1 = new Person("lisi",21,["lida","lier","wangwu"]);
console.log(person1);
var person2 = new Person("wangwu",21,["lida","lier","lisi"]);
console.log(person2);
事件穿透:
阻止:fastclick
实现:https://www.deanhan.cn/js-through.html
是不是数组:
arr instanceof Array
arr.length
arr.constructor === Array
Object.prototype.toString.call(arr) === '[object Array]'
深拷贝浅拷贝:
浅拷贝:直接复制
深拷贝:JSON.parse() JSON.stringify()
或者:
function deepClone(obj){
let objClone = Array.isArray(obj)?[]:{};
if(obj && typeof obj==="object"){
for(key in obj){
if(obj.hasOwnProperty(key)){
//判断ojb子元素是否为对象,如果是,递归复制
if(obj[key]&&typeof obj[key] ==="object"){
objClone[key] = deepClone(obj[key]);
}else{
//如果不是,简单复制
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
闭包:
使用闭包的注意点
(1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
(2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
Ajax 请求过程:
(1)创建`XMLHttpRequest`对象,也就是创建一个异步调用对象.
(2)创建一个新的`HTTP`请求,并指定该`HTTP`请求的方法、`URL`及验证信息.
(3)设置响应`HTTP`请求状态变化的函数.
(4)发送`HTTP`请求.
(5)获取异步调用返回的数据.
(6)使用JavaScript和DOM实现局部刷新.
跨域:(https://segmentfault.com/a/1190000015597029)
跨域原因:同源策略
解决办法 1.jsonp 2.ifream 3.cors(请求头) 4.代理
typeof返回值:
string || number|| undefined || boolean || function|| object
js的原始数据类型有哪些?
string , boolean , number , null , undefined
箭头函数和普通函数有什么区别?
1.箭头函数没有绑定this指针,普通函数的this指向调用函数的对象(匿名函数的this都指向全局window对象);
2.箭头函数没有构造器
数组去重:
1.创建新数组 原数组遍历放入如果有重复则不放入
function uniq(array){
var temp = []; //一个新的临时数组
for(var i = 0; i < array.length; i++){
if(temp.indexOf(array[i]) == -1){
temp.push(array[i]);
}
}
return temp;
}
2.对象键值法去重
function uniq(array){
var temp = {}, r = [], len = array.length, val, type;
for (var i = 0; i < len; i++) {
val = array[i];
type = typeof val;
if (!temp[val]) {
temp[val] = [type];
r.push(val);
} else if (temp[val].indexOf(type) < 0) {
temp[val].push(type);
r.push(val);
}
}
return r;
}
3. 排序后相邻去除法
function uniq(array){
array.sort();
var temp=[array[0]];
for(var i = 1; i < array.length; i++){
if( array[i] !== temp[temp.length-1]){
temp.push(array[i]);
}
}
return temp;
}
4.数组下标法
function uniq(array){
var temp = [];
for(var i = 0; i < array.length; i++) {
//如果当前数组的第i项在当前数组中第一次出现的位置是i,才存入数组;否则代表是重复的
if(array.indexOf(array[i]) == i){
temp.push(array[i])
}
}
return temp;
}
5
function uniq(array){
var temp = [];
var index = [];
var l = array.length;
for(var i = 0; i < l; i++) {
for(var j = i + 1; j < l; j++){
if (array[i] === array[j]){
i++;
j = i;
}
}
temp.push(array[i]);
index.push(i);
}
console.log(index);
return temp;
}
6.new set()
var items = new Set([1, 2, 4, 4, 5]);
var array = Array.from(items);
console.log(array) // (4) [1, 2, 4, 5]
检测一个对象是否有prop属性,没有就抛出异常,有的话返回true,并删掉该属性:
var o = {
age:10,
prop:"prop"
}
function hasProperty(pro,obj){
if(obj.hasOwnProperty(pro)){
delete obj.prop;
}else{
throw new Error("没有该属性");
}
}
hasProperty("prop",o)
console.log(o)
attr()和prop()的区别?
attr是自己定义属性 prop 是修改元素固有属性(checked、disabled ...)
touch和click有何区别?
touch有延迟等待双击事件
Vue的双向绑定原理是什么?
defineProperty
webpack原理是什么?
合并脚本 (require)
get 和 post区别:
(1)post更安全(不会作为url的一部分,不会被缓存、保存在服务器日志、以及浏览器浏览记录中)
(2)post发送的数据更大(get有url长度限制)
(3)post能发送更多的数据类型(get只能发送ASCII字符)
(4)post比get慢
(5)post用于修改和写入数据,get一般用于搜索排序和筛选之类的操作(淘宝,支付宝的搜索查询都是get提交),目的是资源的获取,读取数据
但是在服务器端 get请求更安全,不会修改数据
为什么get比post更快
1.post请求包含更多的请求头
因为post需要在请求的body部分包含数据,所以会多了几个数据描述部分的首部字段(如:content-type),这其实是微乎其微的。
2.最重要的一条,post在真正接收数据之前会先将请求头发送给服务器进行确认,然后才真正发送数据
post请求的过程:
(1)浏览器请求tcp连接(第一次握手)
(2)服务器答应进行tcp连接(第二次握手)
(3)浏览器确认,并发送post请求头(第三次握手,这个报文比较小,所以http会在此时进行第一次数据发送)
(4)服务器返回100 Continue响应
(5)浏览器发送数据
(6)服务器返回200 OK响应
get请求的过程:
(1)浏览器请求tcp连接(第一次握手)
(2)服务器答应进行tcp连接(第二次握手)
(3)浏览器确认,并发送get请求头和数据(第三次握手,这个报文比较小,所以http会在此时进行第一次数据发送)
(4)服务器返回200 OK响应
也就是说,目测get的总耗是post的2/3左右,这个口说无凭,网上已经有网友进行过测试。
3.get会将数据缓存起来,而post不会
可以做个简短的测试,使用ajax采用get方式请求静态数据(比如html页面,图片)的时候,如果两次传输的数据相同,第二次以后消耗的时间将会在10ms以内(chrome测试),而post每次消耗的时间都差不多。经测试,chrome和firefox下如果检测到get请求的是静态资源,则会缓存,如果是数据,则不会缓存,但是IE什么都会缓存起来,当然,应该没有人用post去获取静态数据吧,反正我是没见过。
4.post不能进行管道化传输
http权威指南中是这样说的:http的一次会话需要先建立tcp连接(大部分是tcp,但是其他安全协议也是可以的),然后才能通信,如果 每次连接都只进行一次http会话,那这个连接过程占的比例太大了!于是出现了持久连接:在http/1.0+中是connection首部中添加keep-alive值,在http/1.1中是在connection首部中添加persistent值,当然两者不仅仅是命名上的差别,http/1.1中,持久连接是默认的,除非显示在connection中添加close,否则持久连接不会关闭,而http/1.0+中则恰好相反,除非显示在connection首部中添加keep-alive,否则在接收数据包后连接就断开了。
出现了持久连接还不够,在http/1.1中,还有一种称为管道通信的方式进行速度优化:把需要发送到服务器上的所有请求放到输出队列中,在第一个请求发送出去后,不等到收到服务器的应答,第二个请求紧接着就发送出去,但是这样的方式有一个问题:不安全,如果一个管道中有10个连接,在发送出9个后,突然服务器告诉你,连接关闭了,此时客户端即使收到了前9个请求的答复,也会将这9个请求的内容清空,也就是说,白忙活了……此时,客户端的这9个请求需要重新发送。这对于幂等请求还好(比如get,多发送几次都没关系,每次都是相同的结果),如果是post这样的非幂等请求(比如支付的时候,多发送几次就惨了),肯定是行不通的。
所以,post请求不能通过管道的方式进行通信!很有可能,post请求需要重新建立连接,这个过程不跟完全没优化的时候一样了么?所以,在可以使用get请求通信的时候,不要使用post请求,这样用户体验会更好,当然,如果有安全性要求的话,post会更好。管道化传输在浏览器端的实现还需考证,貌似默认情况下大部分浏览器(除了opera)是不进行管道化传输的,除非手动开启!
get 传参长度原因是由于浏览器本身原因
完整的HTTP请求过程
(https://blog.youkuaiyun.com/u014600626/article/details/78720763)
1.域名解析(DNS解析)
2.发起TCP的3次握手
3.建立TCP连接后发起http请求
4.服务器端响应http请求,浏览器得到html代码
5.浏览器解析html代码,并请求html代码中的资源
6.浏览器对页面进行渲染呈现给用户
手写promise
function Pwromise(exector) {
// 这里我们将value 成功时候的值 reason失败时候的值放入属性中
let self = this;
// 这里我们加入一个状态标识
this.status = 'pending';
this.value = undefined;
this.reason = undefined;
// 成功执行
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 {
exector(resolve, reject);
} catch(e) {
reject(e)
}
}
Pwromise.prototype.then = function(resolve, reject) {
// 获取下this
let self = this;
if(this.status === 'resolved') {
resolve(self.value);
}
if(this.status === 'rejected') {
reject(self.reason);
}
}
function test() {
return new Pwromise((resolve, reject) => {
reject("haha");
}).then(data => {
console.log(data)
}, err => {
console.log(err + '666');
})
}
test()
手写订阅者模式(简单版)
function Public() {
//存放订阅者信息
this.subscribers = [];
//添加订阅者
this.addSubscriber = function(subscriber) {
//保证一个订阅者只能订阅一次
let isExist = this.subscribers.some(function(item) {
return item == subscriber;
})
if(!isExist) {
this.subscribers.push(subscriber);
}
return this;
}
//发布消息
this.deliver = function(data) {
this.subscribers.forEach(function(fn) {
fn(data)
})
return this;
}
}
let a = function(data) {
console.log(`订阅者a收到订阅信息:${data}`)
}
let publisher = new Public();
publisher.addSubscriber(a);
publisher.deliver('这是公众号推送的第1条新信息!');
console.log(publisher)