JS葵花宝典秘籍笔记,为你保驾护航金三银四

所有作为参数传入的值都会变成Arguments对象的数组元素,即使在函数声明中没有指定参数名。

calleelength属性。

  1. callee属性 指代当前正在执行的函数

  2. length属性 传递给函数的参数个数,以及Arguments对象中数组元素的个数

Arguments 对象

arguments 是一个对应于传递给函数的参数的类数组对象。

示例:

function func1(a, b, c) {

console.log(arguments[0]);

// expected output: 1

console.log(arguments[1]);

// expected output: 2

console.log(arguments[2]);

// expected output: 3

}

func1(1, 2, 3);

可以被转换为一个真正的Array:

var args = Array.prototype.slice.call(arguments);

var args = [].slice.call(arguments);

// ES2015

const args = Array.from(arguments);

const args = […arguments];

Arguments对象的主要用途:

  • 用来判断有多少个参数传入函数,还可以用来指代未命名的参数

  • 除了数组元素和length属性,还可以通过callee属性来指代匿名函数本身。

Arguments.callee当前正在执行的函数

arguments.callee,指代当前正在执行的函数,通过它可以引用匿名函数自身。该属性只定义在函数体中。

示例:

// 在匿名函数内使用callee属性来引用匿名函数自身

var fn = function(x) {

if(x<2) return 1;

else return x * arguments.callee(x-1)

}

var y = fn(5); // 120

Arguments.length传给函数的参数个数

arguments.lengthArguments对象的length属性表示给当前函数的参数个数。该属性只能定义在函数体中。

该属性表示的是实际传入的参数个数,不是声明的参数个数。

示例:

alert(“实参长度:” +arguments.length);

alert("形参长度: " +arguments.callee.length);

// 使用Arguments对象来检查传入参数个数的正确性

function check(args) {

var actual = args.length; // 实际的参数个数

var expected = args.callee.length; // 期待的参数个数

if( actual != expected ) {

throw new Error(“参数个数有误,期望值:” + expected + “;实际值:” + actual);

}

}

function fn(x,y,z) {

check(arguments); // 检查参数个数的正确性

return x+y+z;

}

Object.keys()

Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致 。

语法

Object.keys(obj)

参数

obj

要返回其枚举自身属性的对象。

返回值

一个表示给定对象的所有可枚举属性的字符串数组。

示例:

// simple array

var arr = [‘a’, ‘b’, ‘c’];

console.log(Object.keys(arr)); // console: [‘0’, ‘1’, ‘2’]

// array like object

var obj = { 0: ‘a’, 1: ‘b’, 2: ‘c’ };

console.log(Object.keys(obj)); // console: [‘0’, ‘1’, ‘2’]

// array like object with random key ordering

var anObj = { 100: ‘a’, 2: ‘b’, 7: ‘c’ };

console.log(Object.keys(anObj)); // console: [‘2’, ‘7’, ‘100’]

// getFoo is a property which isn’t enumerable

var myObj = Object.create({}, {

getFoo: {

value: function () { return this.foo; }

}

});

myObj.foo = 1;

console.log(Object.keys(myObj)); // console: [‘foo’]

Object.getOwnPropertyNames()

Object.getOwnPropertyNames()方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。

语法Object.getOwnPropertyNames(obj)

参数

obj

一个对象,其自身的可枚举和不可枚举属性的名称被返回。

返回值

在给定对象上找到的自身属性对应的字符串数组。

示例:

var arr = [“a”, “b”, “c”];

console.log(Object.getOwnPropertyNames(arr).sort()); // [“0”, “1”, “2”, “length”]

// 类数组对象

var obj = { 0: “a”, 1: “b”, 2: “c”};

console.log(Object.getOwnPropertyNames(obj).sort()); // [“0”, “1”, “2”]

// 使用Array.forEach输出属性名和属性值

Object.getOwnPropertyNames(obj).forEach(function(val, idx, array) {

console.log(val + " -> " + obj[val]);

});

// 输出

// 0 -> a

// 1 -> b

// 2 -> c

//不可枚举属性

var my_obj = Object.create({}, {

getFoo: {

value: function() { return this.foo; },

enumerable: false

}

});

my_obj.foo = 1;

console.log(Object.getOwnPropertyNames(my_obj).sort()); // [“foo”, “getFoo”]

Object.create()

Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__

const person = {

isHuman: false,

printIntroduction: function() {

console.log(My name is ${this.name}. Am I human? ${this.isHuman});

}

};

const me = Object.create(person);

me.name = ‘Matthew’; // “name” is a property set on “me”, but not on “person”

me.isHuman = true; // inherited properties can be overwritten

me.printIntroduction();

// expected output: “My name is Matthew. Am I human? true”

语法Object.create(proto,[propertiesObject])

参数

proto

新创建对象的原型对象。

propertiesObject

可选。需要传入一个对象,该传入对象的自有可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)将为新创建的对象添加指定的属性值和对应的属性描述符。

返回值

一个新对象,带着指定的原型对象和属性。

例外

如果propertiesObject参数是 null 或非原始包装对象,则抛出一个 TypeError 异常。

用 Object.create实现类式继承

// Shape - 父类(superclass)

function Shape() {

this.x = 0;

this.y = 0;

}

// 父类的方法

Shape.prototype.move = function(x, y) {

this.x += x;

this.y += y;

console.info(‘Shape moved.’);

};

// Rectangle - 子类(subclass)

function Rectangle() {

Shape.call(this); // call super constructor.

}

// 子类续承父类

Rectangle.prototype = Object.create(Shape.prototype);

Rectangle.prototype.constructor = Rectangle;

var rect = new Rectangle();

console.log(‘Is rect an instance of Rectangle?’,

rect instanceof Rectangle); // true

console.log(‘Is rect an instance of Shape?’,

rect instanceof Shape); // true

rect.move(1, 1); // Outputs, ‘Shape moved.’

如果你希望能继承到多个对象,则可以使用混入的方式。

function MyClass() {

SuperClass.call(this);

OtherSuperClass.call(this);

}

// 继承一个类

MyClass.prototype = Object.create(SuperClass.prototype);

// 混合其它

Object.assign(MyClass.prototype, OtherSuperClass.prototype);

// 重新指定constructor

MyClass.prototype.constructor = MyClass;

MyClass.prototype.myMethod = function() {

// do a thing

};

Object.assign 会把 OtherSuperClass 原型上的函数拷贝到 MyClass 原型上,使 MyClass 的所有实例都可用 OtherSuperClass 的方法。

使用 Object.create 的 propertyObject参数

var o;

// 创建一个原型为null的空对象

o = Object.create(null);

o = {};

// 以字面量方式创建的空对象就相当于:

o = Object.create(Object.prototype);

o = Object.create(Object.prototype, {

// foo会成为所创建对象的数据属性

foo: {

writable:true,

configurable:true,

value: “hello”

},

// bar会成为所创建对象的访问器属性

bar: {

configurable: false,

get: function() { return 10 },

set: function(value) {

console.log(“Setting o.bar to”, value);

}

}

});

function Constructor(){}

o = new Constructor();

// 上面的一句就相当于:

o = Object.create(Constructor.prototype);

// 当然,如果在Constructor函数中有一些初始化代码,Object.create不能执行那些代码

// 创建一个以另一个空对象为原型,且拥有一个属性p的对象

o = Object.create({}, { p: { value: 42 } })

// 省略了的属性特性默认为false,所以属性p是不可写,不可枚举,不可配置的:

o.p = 24

o.p

//42

o.q = 12

for (var prop in o) {

console.log(prop)

}

//“q”

delete o.p

//false

//创建一个可写的,可枚举的,可配置的属性p

o2 = Object.create({}, {

p: {

value: 42,

writable: true,

enumerable: true,

configurable: true

}

});

image.png

vue准备工作

  • 学习认识flow,Vuejs源码目录设计,Vuejs源码构建,从入口开始(了解Vue准备)。

  • Flowfacebook出品的JavaScript静态类型检查工具。

  • Vue的源码利用了flow做了静态类型检查。

flow的工作方式:

通常类型检查分为2种:第一种:类型推断;第二种:类型注解。

什么是类型推断呢?

通过变量的使用上下文来推断出变量类型。

什么是类型注解呢?

事先注解好想要的类型,flow会基于这些注解来判断。

在Vuejs的主目录下有.flowconfig文件,是flow的配置文件,[libs]部分是用来描述包含指定库定义的目录。

flow文件夹目录:

  1. compiler.js编译相关

  2. component.js组件数据结构

  3. global-api.jsglobal api结构

  4. modules.js第三方库定义

  5. options.js选项相关

  6. ssr.js服务端渲染相关

  7. vnode.js虚拟node相关

了解Vue.js源码目录src下:

  1. compiler编译相关

  2. core核心代码

  3. platforms不同平台的支持

  4. server服务端渲染

  5. sfc-.vue文件解析

  6. shared共享代码

Vuejs源码是基于Rollup构建的。

Vue 初始化过程

推荐:Vue 初始化过程

init流程图

image.png

Vue的本质:其实就是一个用Function实现的Class,通过它的原型prototype以及它本身扩展的一系列的方法和属性。

对数据渲染的过程有了更深的一层理解,从new Vue()开始,创建了一个vue是对象,会先进行init初始化——>$mount()——>compile(若已经是render则该过程不需要)——>render——>创建VNode——>patch过程——>生成真实的DOM

null

如果想要任意类型T可以为null或者是undefined,只需写为?T的格式。

var foo: string = null

// 可以是字符串,也可以是null

Vue项目中为什么要在列表组件中写key,其作用是什么

key是给每个vnode的唯一的id,可以依靠key,更准确,更快的拿到oldVnode中对应的vnode节点。

['1','2','3'].map(parseInt)

image.png

答案是[1,NaN,NaN],为什么不是[1,2,3]呢?

map函数的第一个参数callback,这个callback一共可以接收三个参数,其中第一个参数代表当前被处理的元素,而第二个参数代表该元素的索引。

arr.map(callback: (value:T, index: number, array: T[]) => U, thisArg?:any);

  • parseInt是用来解析字符串的,使得字符串成为指定基数的整数。接收两个参数,第一个表示被处理的值(字符串),第二个表示为解析时的基数。

parseInt(string, radix);

parseINT('1', 0) 表示 radix 为0时,且string参数不以"0x"和"0"开头时,按照10为基数进行处理,返回为1。

parseInt('2',1),基数为1,(1进制),表示的数中,最大值小于2,所以无法解析,返回为NaN。

image.png

什么是防抖和节流

防抖,字面意思放置的手抖再次触发。

onReachBottom() {

this.timer && clearTimeout(this.timer)

this.timer = setTimeout(this.getMoreList, 300)

},

触发高频事件后n秒后函数只会执行一次,如果n秒内高频事件再次被触发,则需要重新计算时间。

// 掘金:魔王哪吒

// 实现input实时搜索

function debounce(fn) {

let timeout = null

// 创建一个标记用来存放定时器的返回值

return function() {

clearTimeout(timeout)

// 每当用户输入的时候把前一个setTimeout clear掉

timeout = setTimeout(() => {

// 创建一个新的setTimeout,这样就能保证输入字符串后的interval间隔内如果还有字符输入的话,就不会执行fn函数

fn.apply(this, arguments);

},500)

}

}

function sayHi() {

console.log(‘防抖成功’)

}

var inp = document.getElementById(‘inp’);

inp.addEventListener(‘input’,debounce(sayHi)); // 防抖

节流,字面节约流量,高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执 行频率。

// 掘金:魔王哪吒

function throttle(fn) {

let canRun = true; // 通过闭包保持一个标记

return function() {

if(!canRun) return

// 在函数开头判断标记是否为true,不为true则return

canRun = false // 立即设置为false

setTimeout(() => {

fn.apply(this,argument);

// 最后在setTimeout执行完毕后再把标记设置为true表示可以执行下一次循环了,当定时器没有执行的时候标记为false

canRun = true

},500)

}

}

function sayHi(e) {

console.log(e.target.innerWidth, e.target.innerHeight)

}

window.addEventListener(‘resize’, throttle(sayHi));

Set, Map, WeakSet, WeakMap

set,对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用

weakset,成员都是对象,成员都是弱引用,可以被垃圾回收机制回收,可以用来保存DOM节点不容易造成内存泄漏

Map,本质上是键值对的集合,类似集合,可以遍历,方法很多,可以跟各种数据格式转换。

WeakMap,只接收对象为键名(null除外),不接收其他类型的值作为键名,键名是弱引用,键值可以是任意的键名所指向的对象可以被垃圾回收,此时键名是无效的,不能遍历,方法有get,set,has,delete

深度优先遍历和广度优先遍历

深度优先遍历

指从某个顶点出发,首先访问这个顶点,然后找出刚访问 这个结点的第一个未被访问的邻结点,然后再以此邻结点为顶点,继续找它的 下一个顶点进行访问。重复此步骤,直至所有结点都被访问完为止。

广度优先遍历

是从某个顶点出发,首先访问这个顶点,然后找出刚访问这个结点所有未被访问的邻结点,访问完后再访问这些结点中第一个邻结点的所有结点,重复此方法,直到所有结点都被访问完为止。

//1.深度优先遍历的递归写法

function deepTraveral(node) {

let nodes = []

if(node != null) {

nodes.push[node]

let childrens = node.children

for(let i=0; i<childrens.length; i++) deepTraversal(childrens[i])

}

return nodes

}

//2.深度优先遍历的非递归写法

function deepTraversal(node) {

let nodes = []

if(node != null) {

let stack = []

// 用来存放将来要访问的节点

stack.push(node)

while(stack.length != 0) {

let item = stack.pop()

// 正在访问的节点

nodes.push(item)

let childrens = item.children

for(let i = childrens.length-1; i>=0; i–) stack.push(childrens[i])

// 将现在访问点的节点的子节点存入stack,供将来访问

}

}

return nodes

}

//3.广度优先遍历的递归写法

function wideTraversal(node) {

let nodes = [], i = 0

if(node != null) {

nodes.push(node)

wideTraversal(node.nextElementSibling)

node = nodes[i++]

wideTraversal(node.firstElementChild)

}

return nodes

}

//4.广度优先遍历的非递归写法

function wideTraversal(node) {

let nodes = [], i=0

while(node != null) {

nodes.push(node)

node = nodes[i++];

let childrens = node.children

for(let i=0; i<childrens.length; i++) {

nodes.push(childrens[i])

}

}

return nodes

}

实现一个拷贝函数?

Object.prototype.toString()

toString() 方法返回一个表示该对象的字符串。

function Dog(name) {

this.name = name;

}

const dog1 = new Dog(‘掘金魔王哪吒’);

Dog.prototype.toString = function dogToString() {

return ${this.name};

};

console.log(dog1.toString());

// expected output: “掘金魔王哪吒”

语法

obj.toString()

// 返回值

// 一个表示该对象的字符串。

每个对象都有一个 toString() 方法,当该对象被表示为一个文本值时,或者一个对象以预期的字符串方式引用时自动调用。默认情况下,toString() 方法被每个 Object 对象继承。如果此方法在自定义对象中未被覆盖,toString() 返回 "[object type]",其中 type 是对象的类型。

var o = new Object();

o.toString(); // returns [object Object]

使用 toString() 检测对象类型

可以通过 toString() 来获取每个对象的类型。为了每个对象都能通过 Object.prototype.toString() 来检测,需要以 Function.prototype.call() 或者 Function.prototype.apply() 的形式来调用,传递要检查的对象作为第一个参数,称为 thisArg

示例:

var toString = Object.prototype.toString;

toString.call(new Date); // [object Date]

toString.call(new String); // [object String]

toString.call(Math); // [object Math]

//Since JavaScript 1.8.5

toString.call(undefined); // [object Undefined]

toString.call(null); // [object Null]

Function.prototype.call()

call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。

call() 方法接受的是一个参数列表

示例:

// 掘金:魔王哪吒

function Product(name, price) {

this.name = name;

this.price = price;

}

function Food(name, price) {

Product.call(this, name, price);

this.category = ‘food’;

}

console.log(new Food(‘cheese’, 5).name);

// expected output: “cheese”

语法

function.call(thisArg, arg1, arg2, …)

thisArg

可选的。在 function 函数运行时使用的 this 值。请注意,this可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动替换为指向全局对象,原始值会被包装。

arg1, arg2, ...

指定的参数列表。

返回值

使用调用者提供的 this 值和参数调用该函数的返回值。若该方法没有返回值,则返回 undefined

描述

call() 允许为不同的对象分配和调用属于一个对象的函数/方法。

call() 提供新的 this 值给当前调用的函数/方法。你可以使用 call 来实现继承:写一个方法,然后让另外一个新的对象来继承它(而不是在新对象中再写一次这个方法)。

使用 call 方法调用父构造函数

示例:

// 掘金:魔王哪吒

function Product(name, price) {

this.name = name;

this.price = price;

}

function Food(name, price) {

Product.call(this, name, price);

this.category = ‘food’;

}

function Toy(name, price) {

Product.call(this, name, price);

this.category = ‘toy’;

}

var cheese = new Food(‘feta’, 5);

var fun = new Toy(‘robot’, 40);

Function.prototype.apply()

apply() 方法调用一个具有给定this值的函数,以及以一个数组(或类数组对象)的形式提供的参数。

image.png

语法

// 掘金:魔王哪吒

func.apply(thisArg, [argsArray])

参数

thisArg

必选的。在 func 函数运行时使用的 this 值。请注意,this可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动替换为指向全局对象,原始值会被包装。

argsArray

可选的。一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 func 函数。如果该参数的值为 null 或 undefined,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。

返回值

调用有指定this值和参数的函数的结果。

描述

在调用一个存在的函数时,你可以为其指定一个 this 对象。 this 指当前对象,也就是正在调用这个函数的对象。 使用 apply, 你可以只写一次这个方法然后在另一个对象中继承它,而不用在新对象中重复写该方法。

用 apply 将数组各项添加到另一个数组

// 掘金:魔王哪吒

var array = [‘a’, ‘b’];

var elements = [0, 1, 2];

array.push.apply(array, elements);

console.info(array); // [“a”, “b”, 0, 1, 2]

Function.prototype.bind()

bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。

// 掘金:魔王哪吒

const module = {

x: 42,

getX: function() {

return this.x;

}

};

const unboundGetX = module.getX;

console.log(unboundGetX()); // The function gets invoked at the global scope

// expected output: undefined

const boundGetX = unboundGetX.bind(module);

console.log(boundGetX());

// expected output: 42

语法

// 掘金:魔王哪吒

function.bind(thisArg[, arg1[, arg2[, …]]])

返回值

返回一个原函数的拷贝,并拥有指定的 this 值和初始参数。

image.png

创建绑定函数

// 掘金:魔王哪吒

this.x = 9; // 在浏览器中,this 指向全局的 “window” 对象

var module = {

x: 81,

getX: function() { return this.x; }

};

module.getX(); // 81

var retrieveX = module.getX;

retrieveX();

// 返回 9 - 因为函数是在全局作用域中调用的

// 创建一个新函数,把 ‘this’ 绑定到 module 对象

// 新手可能会将全局变量 x 与 module 的属性 x 混淆

var boundGetX = retrieveX.bind(module);

boundGetX(); // 81

在默认情况下,使用 window.setTimeout() 时,this 关键字会指向 window (或 global)对象。当类的方法中需要 this 指向类的实例时,你可能需要显式地把 this 绑定到回调函数,就不会丢失该实例的引用。

将一个类似于数组的对象转换成一个真正的数组

// 掘金:魔王哪吒

var slice = Array.prototype.slice;

// …

slice.apply(arguments);

Array.prototype.slice()

slice() 方法返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括end)。原始数组不会被改变。

// 掘金:魔王哪吒

const animals = [‘ant’, ‘bison’, ‘camel’, ‘duck’, ‘elephant’];

console.log(animals.slice(2));

// expected output: Array [“camel”, “duck”, “elephant”]

console.log(animals.slice(2, 4));

// expected output: Array [“camel”, “duck”]

console.log(animals.slice(1, 5));

// expected output: Array [“bison”, “camel”, “duck”, “elephant”]

语法

// 掘金:魔王哪吒

arr.slice([begin[, end]])

返回值

一个含有被提取元素的新数组。

描述

slice 不会修改原数组,只会返回一个浅复制了原数组中的元素的一个新数组。原数组的元素会按照下述规则拷贝:

如果该元素是个对象引用 (不是实际的对象),slice 会拷贝这个对象引用到新的数组里。两个对象引用都引用了同一个对象。如果被引用的对象发生改变,则新的和原来的数组中的这个元素也会发生改变。

对于字符串、数字及布尔值来说(不是 String、Number 或者 Boolean 对象),slice 会拷贝这些值到新的数组里。在别的数组里修改这些字符串或数字或是布尔值,将不会影响另一个数组。

如果向两个数组任一中添加了新元素,则另一个不会受到影响。

类数组(Array-like)对象

slice 方法可以用来将一个类数组(Array-like)对象/集合转换成一个新数组。你只需将该方法绑定到这个对象上。 一个函数中的 arguments 就是一个类数组对象的例子。

// 掘金:魔王哪吒

function list() {

return Array.prototype.slice.call(arguments);

}

var list1 = list(1, 2, 3); // [1, 2, 3]

除了使用 Array.prototype.slice.call(arguments),你也可以简单的使用 [].slice.call(arguments) 来代替。

可以使用 bind 来简化该过程

// 掘金:魔王哪吒

var unboundSlice = Array.prototype.slice;

var slice = Function.prototype.call.bind(unboundSlice);

function list() {

return slice(arguments);

}

var list1 = list(1, 2, 3); // [1, 2, 3]

环状数据

// 掘金:魔王哪吒

const obj = {

foo: {

name: ‘foo’,

bar: {

name: ‘bar’

baz: {

name: ‘baz’,

aChild: null //待会让它指向obj.foo

}

}

}

}

obj.foo.bar.baz.aChild = obj.foo // foo->bar->baz->aChild->foo 形成环

JSON.stringify(obj) // => TypeError: Converting circular structure to JSON

拷贝这样封闭的环状数据结构,会导致死循环

先说说什么是深拷贝与浅拷贝

image.png

浅拷贝:也就是拷贝A对象里面的数据,但是不拷贝A对象里面的子对象

深拷贝:会克隆出一个对象,数据相同,但是引用地址不同(就是拷贝A对象里面的数据,而且拷贝它里面的子对象)

浅拷贝和深拷贝的区别

image.png

推荐: 请分别用深度优先思想和广度优先思想实现一个拷贝函数? 每日一题系列(六)")

uniapp实现小程序微信登录

推荐:企业微信开放平台注册流程

推荐:uniapp实现小程序微信登录

补充:app生成签名证书

testalias 和 test.keystore中的'test'都是可以修改的,可以替换为自己项目中的名字。输入下面的keytool -genkey命令就可以生成证书了

keytool -genkey -alias testalias -keyalg RSA -keysize 2048 -validity 36500 -keystore test.keystore

用签名生成工具生成签名

image.png

uniapp的mainfest.json文件配置中,appid必须是'_UNI_'开头,所以你的配置文件中得是'_UNI_'开头的。

推荐:小程序静默登录方案设计

推荐:小程序用户登录架构设计

登录方案

  • Cookie + Session 登录

  • Token 登录

  • SSO 单点登录

  • OAuth 第三方登录

SSO 单点登录,适用于中大型企业,想要统一内部所有产品的登录方式的情况。

实现垂直居中

// 掘金:魔王哪吒

flex

margin: 0 auto

canvas如何实现按比例沾满全屏

  • document.documentElement.clientWidth: 可见区域宽度;

  • document.documentElement.clientHeight: 可见区域高度。

  • canvas.width = document.documentElement.clientWidth

  • canvas.height = document.documentElement.clientHeight

  • screen.availWidth:屏幕可用宽度;

  • screen.availHeight:屏幕可见高度。

  • canvas.width = screen.availWidth;

  • canvas.height = screen.availHeight;

  • screen.width:屏幕显示宽度

  • screen.height:屏幕显示高度

  • canvas.width = screen.width

  • canvas.height = screen.height

  • window.innerWidth:窗口的宽度

  • window.innerHeight:窗口的高度

  • canvas.width = window.innerWidth

  • canvas.height = window.innerHeight

Vue2.0

Vue源码根目录下文件夹:

  • build打包相关的配置文件,根据不同的入口,打包为不同的文件

  • dist打包之后文件所在位置

  • examples部分示例

  • flow,因Vue使用了Flow来进行静态类型检查,这里是定义了声明一些静态类型

  • packages,分别生成其他的npm

  • src,主要源码所在位置

  • compiler模板解析的相关文件

  • codegen根据ast生成render函数

  • directives通用生成render函数之前需要处理的指令

  • parser模板解析

  • core核心代码

  • components全局组件

  • global-api全局方法

  • instance实例相关内容,包括实例方法,生命周期,事件等

  • observer双向数据绑定相关文件

  • util工具方法

  • vdom虚拟dom相关

  • entries入口文件,也就是build文件夹下config.js中配置的入口文件

  • platforms平台相关的内容

  • webweb端独有文件

  • compiler编译阶段需要处理的指令和模块

  • runtime运行阶段需要处理的组件,指令和模块

  • server服务端渲染相关

  • util工具库

  • weexweex端独有文件

  • shared共享的工具方法

  • test测试用例

从入口文件查看Vue源码

先看package.json文件,有项目的依赖,有开发环境,生产环境等编译的启动脚本,有项目的许可信息等。来看看:npm run dev

// 掘金:魔王哪吒

“dev”: “rollup -w -c build/config.js --environment TARGET:web-full-dev”

rollup是一个类似于webpack的打包工具,入口文件:/src/entries/web-runtime-with-compiler.js

// 掘金:魔王哪吒

/src/entries/web-runtime-with-compiler.js

–> /src/entries/web-runtime.js

–> /src/core/index.js

–> /src/core/instance/index.js

定义Vue对象它的构造函数及其简单:

// 掘金:魔王哪吒

function Vue (options) {

// 判断是不是生产环境

if (process.env.NODE_ENV !== ‘production’ &&

!(this instanceof Vue)) {

//如果不是通过new关键字来创建对象的话

warn(‘Vue is a constructor and should be called with the new keyword’)

}

this._init(options)

}

Vue的静态方法和实例方法:

// src/core/index.js

Vue.version = ‘VERSION

// src/entries/web-runtime-with-compiler.js

Vue.compile = compileToFunctions

// 把模板template转换为render函数

// src/core/global-api

// 在目录结构中,Vue的静态方法大多都是在该文件夹中定义的

// src/core/global-api/index.js

Vue.config

Vue.util

Vue.set

Vue.delete

Vue.nextTick

Vue.options = {

components: {KeepAlive: KeepAlive}

directives: {},

filters: {},

_base: Vue

}

// src/core/global-api/use.js

Vue.use

// src/core/global-api/mixin.js

Vue.mixin

// src/core/global-api/extend.js

Vue.extend

// src/core/global-api/assets.js

Vue.component

Vue.directive

Vue.filter

vm._uid // 自增的id

vm._isVue // 标示是vue对象,避免被observe

vm._renderProxy // Proxy代理对象

vm._self // 当前vm实例

vm.$parent // 用于自定义子组件中,指向父组件的实例

vm.$root // 指向根vm实例

vm.$children // 当前组件的子组件实例数组

vm.$refs

vm._watcher = null

vm._inactive = null

vm._directInactive = false

vm._isMounted = false // 标识是否已挂载

vm._isDestroyed = false // 标识是否已销毁

vm._isBeingDestroyed = false // 标识是否正在销毁

vm._events // 当前元素上绑定的自定义事件

vm._hasHookEvent // 标示是否有hook:开头的事件

vm. v n o d e / / 当前自定义组件在父组件中的 v n o d e ,等同于 v m . vnode // 当前自定义组件在父组件中的vnode,等同于vm. vnode//当前自定义组件在父组件中的vnode,等同于vm.options._parentVnode

vm._vnode // 当前组件的vnode

vm._staticTrees // 当前组件模板内分析出的静态内容的render函数数组

vm.$el // 当前组件对应的根元素

vm.$slots // 定义在父组件中的slots,是个对象键为name,值为响应的数组

vm.$scopedSlots = emptyObject

// 内部render函数使用的创建vnode的方法

vm._c = (a, b, c, d) => createElement(vm, a, b, c, d, false)

// 用户自定义render方法时,传入的参数

vm.$createElement = (a, b, c, d) => createElement(vm, a, b, c, d, true)

vm._props // 被observe的存储props数据的对象

vm._data // 被observe的存储data数据的对象

vm._computedWatchers // 保存计算属性创建的watcher对象

钩子函数:

  • beforeCreate,创建之前

  • created,创建

  • beforeMount,挂载前

  • mounted,挂载

  • beforeUpdate,更新前

  • updated,更新

  • activated,触发

  • deactivated,停用

  • beforeDestroy,销毁前

  • destroyed,毁坏

// vm.$options

declare type ComponentOptions = {

// data

data: Object | Function | void; // 传入的data数据

props?: { [key: string]: PropOptions }; // props传入的数据

propsData?: ?Object; // 对于自定义组件,父级通过props传过来的数据

computed?: { // 传入的计算属性

[key: string]: Function | {

get?: Function;

set?: Function;

cache?: boolean

}

};

methods?: { [key: string]: Function }; // 传入的方法

watch?: { [key: string]: Function | string }; // 传入的watch

// DOM

el?: string | Element; // 传入的el字符串

template?: string; // 传入的模板字符串

render: (h: () => VNode) => VNode; // 传入的render函数

renderError?: (h: () => VNode, err: Error) => VNode;

staticRenderFns?: Array<() => VNode>;

// 钩子函数

beforeCreate?: Function;

created?: Function;

beforeMount?: Function;

mounted?: Function;

beforeUpdate?: Function;

updated?: Function;

activated?: Function;

deactivated?: Function;

beforeDestroy?: Function;

destroyed?: Function;

// assets

directives?: { [key: string]: Object }; // 指令

components?: { [key: string]: Class }; // 子组件的定义

transitions?: { [key: string]: Object };

filters?: { [key: string]: Function }; // 过滤器

// context

provide?: { [key: string | Symbol]: any } | () => { [key: string | Symbol]: any };

inject?: { [key: string]: string | Symbol } | Array;

// component v-model customization

model?: {

prop?: string;

event?: string;

};

// misc

parent?: Component; // 父组件实例

mixins?: Array; // mixins传入的数据

name?: string; // 当前的组件名

extends?: Class | Object; // extends传入的数据

delimiters?: [string, string]; // 模板分隔符

// 私有属性,均为内部创建自定义组件的对象时使用

_isComponent?: true; // 是否是组件

_propKeys?: Array; // props传入对象的键数组

_parentVnode?: VNode; // 当前组件,在父组件中的VNode对象

_parentListeners?: ?Object; // 当前组件,在父组件上绑定的事件

_renderChildren?: ?Array; // 父组件中定义在当前元素内的子元素的VNode数组(slot)

_componentTag: ?string; // 自定义标签名

_scopeId: ?string;

_base: Class; // Vue

_parentElm: ?Node; // 当前自定义组件的父级dom结点

_refElm: ?Node; // 当前元素的nextSlibing元素,即当前dom要插入到_parentElm结点下的_refElm前

}

拿到一个函数的返回值类型,使用TS

const func = (): number => 1;

// 声明一个泛型类型别名,返回值与泛型类型相同,入参类型不限制。

type Reverse = (arg: any) => T;

// 声明一个泛型方法,入参arg继承泛型约束,返回空对象并断言其类型为T

function returnResultType(arg: Reverse): T {

return {} as T;

}

// 调用returnResultType,传入方法(arg: any) => 3,获得result返回值

const result = returnResultType((arg:any) => 3);

// 获取result类型并重名为ResultType

type ResultType = typeof result;

Array

构造函数:

new Array()

new Array(size)

new Array(element0, element1, …, elementn)

  • size设定的数组元素个数。返回数组的length属性等于size

  • 参数列表,element0,..,elementn,当Array()构造函数用这些参数调用时,新创建的数组实例会用指定的参数值来初始化,并将length属性设置为参数个数。

  • 当不带参数调用Array()时,返回的数组为空,length属性为0。

  • concat(),把元素衔接到数组中。

  • every(),测试断言函数是否对每个数组元素都为真。

  • filter(),返回满足断言函数的数组元素。

  • forEach(),为数组的每一个元素调用指定函数。

  • indexOf(),在数组中查找匹配元素。

  • join(),将数组的所有元素转换为字符串,并衔接起来。

  • lastIndexOf(),在数组中反向查找。

  • map(),从数组的元素中,计算出新的数组元素。

  • pop(),移除数组最后一个元素。

  • push(),把元素添加到数组尾部。

  • reduce(),从数组的元素中,计算出一个值。

  • reduceRight(),从右到左缩减数组。

  • reverse(),在原数组中颠倒元素的顺序。

  • shift(),移除数组的第一个元素。

  • slice(),返回数组的一部分。

  • some(),测试是否至少有一个数组元素能让断言函数为真。

  • sort(),在原数组中对数组元素进行排序。

  • splice(),插入,删除,或替换数组元素。

  • toLocaleString(),将数组转换为本地字符串。

  • toString(),将数组转换为字符串。

  • unshift(),在数组头部插入元素。

Array.concat()

array.concat(value, …)

返回值,一个新数组,包含array的元素,以及衔接的新元素。

concat()会将参数衔接到array中得到一个新数组并返回,它不会修改array,如果传给concat()的某个参数本身是一个数组,则会将该数组的元素衔接到array中,而不是数组本身。

var a = [1,2,3];

a.concat(4,5); // [1,2,3,4,5];

Array.every()测试断言函数是否对每个元素为真

array.every(predicate)

array.every(predicate,o)

参数:

  • predicate,用来测试数组元素的断言函数。

  • o,调用predicate时的可选this值。

返回值:如果对array的每一个元素调用predicate时都返回真值,则返回true,如果有任何一个元素调用predicate时返回假值,则返回false

every()方法用来测试数组的所有元素是否都满足某些条件。如果predicate的每一次调用都返回true,则every()返回true,否则,为false

当遍历的数组为空时,every()返回true

[1,2,3].every(function(x) { return x<5 ;}) // true

[1,2,3].every(function(x) { return x<3 ;}) // false

[].every(function(x) {return false;}); // true []总是返回true

Array.filter()返回通过断言的数组元素

  • array.map(predicate)

  • array.map(predicate, o)

  • predicate,用来判断array中的元素是否需要包含在返回数组中的调用函数

  • o,调用predicate时的可选this

返回值:

一个新数组,只包含那些让predicate返回真值的数组元素

filter()会创建一个新数组,包含那些让predicate函数返回真值的array的元素。filter()方法不会修改arrry本身,注意predicate函数有可能会修改。

返回新创建的数组。

Array.forEach()为每一个数组元素调用一个函数

array.forEach(f)

array.forEach(f,o)

参数

f 为array的每一个元素调用的函数

o 调用f时的可选this值

返回值:该方法无返回值,注意forEach()没有返回值,特别注意,它不会返回array

forEach(), map(), filter(), every(), some()接受函数作为第一个参数,并接受可选的第二个参数。在函数体内,this值等于o。

如果没有指定第二个参数,this值在非严格模式下是全局对象,在严格模式下则为null

var a = [1,2,3];

a.forEach(function(x,i,a){ a[i]++; }); // [2,3,4]

Array.indexOf()查找数组

array.indexOf(value)

array.indexOf(value,start)

参数:

value 要在array中查找的值

start 开始查找的可选数组序号,可以省略,则为0

返回值,所在index,如果不存在匹配元素时,返回-1

判断是否相等使用的是"==="操作符

[‘a’, ‘b’, ‘c’].indexOf(‘b’); // 1

[‘a’, ‘b’, ‘c’].indexOf(‘d’, 1); // -1

Array.join(),将数组元素衔接为字符串

array.join()

array.join(separator)

  • separator,在返回的字符串中,用来分隔数组的某个元素与下一个元素的可选字符或字符串。如果省略,默认是英文逗号。

返回值,一个字符串。

a = new Array(1,2,3,“test”);

s = a.join(“+”); // 1+2+3+test

Array.lastIndexOf()反向查找数组

array.lastIndexOf(value);

array.lastIndexOf(value,start);

  • value,要在array中查找的值

  • start,开始查找的可选数组序号,如果省略,则从最后一个元素开始查找

Array.length数组大小

length属性表示数组中的元素个数

如果设置的length大于原值,数组会变大,新添加到末尾处的元素的值为undefined

Array.map()从数组元素中计算新值

array.map(f);

array.map(f,o);

  • f为array的每一个元素调用的函数,它的返回值会成为返回数组的元素。

  • o-f调用时的可选this值。

返回值:一个新数组,由函数f计算出的元素组成。

[1,2,3].map(function(x) { return x*x }); // [1,4,9]

Array.pop()移除并返回数组的最后一个元素

array.pop()

返回值:array的最后一个元素

pop()会移除array的最后一个元素,缩短数组的长度,并返回所移除元素的值。如果数组已经为空,pop()不会修改该数组,返回值为undefined

pop()push(),先进后出的栈功能:

var stack = []; // stack: []

stack.push(1,2); // stack: [1,2] 返回2

stack.pop(); // stack: [1] 返回2

stack.push([4,5]); // stack: [1, [4,5]] 返回2

stack.pop(); // stack: [1] 返回[4,5]

stack.pop(); // stack: [] 返回1

Array.push()给数组追加元素

array.push(value,…);

返回值:把指定值追加到数组后数组的新长度。(它会直接修改array,而不会创建一个新的数组)

push()pop(),先进后出的栈功能。

Array.reduce()从数组元素中计算一个值

array.reduce(f);

array.reduce(f,initial);

  • f一个函数,可以合并两个值,并返回一个“缩减”的新值。

  • initial,用来缩减数组的可选初始值,如果指定该参数,reduce()的行为会像把该参数插入array的头部一样。

返回值:数组的化简值

示例:

[1,2,3,4].reduce(function(x,y) { return x*y; }) // 24

Array.reduceRight()从右到左缩减数组

array.reduceRight(f)

array.reduceRight(f, initial)

  • f一个函数,可以合并两个值,并返回一个“缩减”的新值。

  • initial用来缩减数组的可选初始值,如果指定该参数,reduceRight()的行为会像是把该参数插入aray的尾部一样。

返回值:数组的缩减值,该值是最后一次调用f时的返回值。

[2,10,60].reduceRight(function(x,y) { return x/y; }) // 3

Array.reverse()颠倒数组中的元素顺序

array.reverse()

Array对象的reverse()方法可以颠倒数组元素的顺序。它会在原数组中进行操作,而不会创建一个新数组。

a = new Array(1,2,3);

a.reverse();

Array.shift()移除数组的第一个元素

array.shift()

返回值:数组原来的第一个元素。

如果数组为空,shift()什么也不干,返回undefined值,没有创建新数组。

var a = [1,[2,3],4];

a.shift(); // 1

Array.slice()返回数组的一部分

array.slice(start, end)

返回值:一个新数组,包含array中从start一直到end之间的所有元素(包含start指定的元素,但不包含end指定的元素),如果没有指定end,返回的数组包含从start到array尾部的所有元素。

var a = [1,2,3,4,5];

a.slice(0,3); // 返回 [1,2,3]

a.slice(3); // 返回 [4,5]

Array.some()测试是否有元素满足断言函数

array.some(predicate)

array.some(predicate,o)

  • predicate用来测试数组元素的断言函数

  • o调用predicate时的可选this

返回值:如果array中有至少一个元素调用predicate时返回真值,则返回true,如果所有元素调用predicate时都返回假值,则返回false。

[1,2,3].some(function(x) { return x>5; }); //false

[1,2,3].some(function(x) { return x>2; }); // true

[].some(function(x) { return false; }); // false

Array.sort()对数组元素进行排序

array.sort()

array.sort(orderfunc)

  • orderfunc用来指定如何排序的可选函数

返回值:该数组的引用。注意是在原数组中进行排序,没有新键数组。数组中的undefined元素会始终排列在数组末尾。

function numberorder(a,b) {return a-b;}

a = new Array(3,2,4);

a.sort(); // 字母排序

a.sort(numberorder); // 数值排序

Array.splice()插入,删除或替换数组元素

array.splice(start,deleteCount,value,…)

  • start开始插入和删除处的数组元素的序号。

  • deleteCount要删除的元素个数,从start开始,并包含start处的元素,如果指定为0,表示插入元素,而不用删除任何元素。

  • value,...要插入数组中的零个或多个值,从start序号开始插入。

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
[1, [4,5]] 返回2

stack.pop(); // stack: [1] 返回[4,5]

stack.pop(); // stack: [] 返回1

Array.push()给数组追加元素

array.push(value,…);

返回值:把指定值追加到数组后数组的新长度。(它会直接修改array,而不会创建一个新的数组)

push()pop(),先进后出的栈功能。

Array.reduce()从数组元素中计算一个值

array.reduce(f);

array.reduce(f,initial);

  • f一个函数,可以合并两个值,并返回一个“缩减”的新值。

  • initial,用来缩减数组的可选初始值,如果指定该参数,reduce()的行为会像把该参数插入array的头部一样。

返回值:数组的化简值

示例:

[1,2,3,4].reduce(function(x,y) { return x*y; }) // 24

Array.reduceRight()从右到左缩减数组

array.reduceRight(f)

array.reduceRight(f, initial)

  • f一个函数,可以合并两个值,并返回一个“缩减”的新值。

  • initial用来缩减数组的可选初始值,如果指定该参数,reduceRight()的行为会像是把该参数插入aray的尾部一样。

返回值:数组的缩减值,该值是最后一次调用f时的返回值。

[2,10,60].reduceRight(function(x,y) { return x/y; }) // 3

Array.reverse()颠倒数组中的元素顺序

array.reverse()

Array对象的reverse()方法可以颠倒数组元素的顺序。它会在原数组中进行操作,而不会创建一个新数组。

a = new Array(1,2,3);

a.reverse();

Array.shift()移除数组的第一个元素

array.shift()

返回值:数组原来的第一个元素。

如果数组为空,shift()什么也不干,返回undefined值,没有创建新数组。

var a = [1,[2,3],4];

a.shift(); // 1

Array.slice()返回数组的一部分

array.slice(start, end)

返回值:一个新数组,包含array中从start一直到end之间的所有元素(包含start指定的元素,但不包含end指定的元素),如果没有指定end,返回的数组包含从start到array尾部的所有元素。

var a = [1,2,3,4,5];

a.slice(0,3); // 返回 [1,2,3]

a.slice(3); // 返回 [4,5]

Array.some()测试是否有元素满足断言函数

array.some(predicate)

array.some(predicate,o)

  • predicate用来测试数组元素的断言函数

  • o调用predicate时的可选this

返回值:如果array中有至少一个元素调用predicate时返回真值,则返回true,如果所有元素调用predicate时都返回假值,则返回false。

[1,2,3].some(function(x) { return x>5; }); //false

[1,2,3].some(function(x) { return x>2; }); // true

[].some(function(x) { return false; }); // false

Array.sort()对数组元素进行排序

array.sort()

array.sort(orderfunc)

  • orderfunc用来指定如何排序的可选函数

返回值:该数组的引用。注意是在原数组中进行排序,没有新键数组。数组中的undefined元素会始终排列在数组末尾。

function numberorder(a,b) {return a-b;}

a = new Array(3,2,4);

a.sort(); // 字母排序

a.sort(numberorder); // 数值排序

Array.splice()插入,删除或替换数组元素

array.splice(start,deleteCount,value,…)

  • start开始插入和删除处的数组元素的序号。

  • deleteCount要删除的元素个数,从start开始,并包含start处的元素,如果指定为0,表示插入元素,而不用删除任何元素。

  • value,...要插入数组中的零个或多个值,从start序号开始插入。

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-wdtwyRfE-1715823570362)]

[外链图片转存中…(img-Nd40bSrG-1715823570362)]

[外链图片转存中…(img-4JVwz2S7-1715823570363)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值