1、首先是定义
进程:是执行中一段程序,即一旦程序被载入到内存中并准备执行,它就是一个进程。进程是表示资源分配的的基本概念,又是调度运行的基本单位,是系统中的并发执行的单位。
线程:单个进程中执行中每个任务就是一个线程。线程是进程中执行运算的最小单位。
2、一个线程只能属于一个进程,但是一个进程可以拥有多个线程。多线程处理就是允许一个进程中在同一时刻执行多个任务。
3、线程是一种轻量级的进程,与进程相比,线程给操作系统带来侧创建、维护、和管理的负担要轻,意味着线程的代价或开销比较小。
4、线程没有地址空间,线程包含在进程的地址空间中。线程上下文只包含一个堆栈、一个寄存器、一个优先权,线程文本包含在他的进程 的文本片段中,进程拥有的所有资源都属于线程。所有的线程共享进程的内存和资源。 同一进程中的多个线程共享代码段(代码和常量),数据段(全局变量和静态变量),扩展段(堆存储)。但是每个线程拥有自己的栈段, 寄存器的内容,栈段又叫运行时段,用来存放所有局部变量和临时变量。
5、父和子进程使用进程间通信机制,同一进程的线程通过读取和写入数据到进程变量来通信。
6、进程内的任何线程都被看做是同位体,且处于相同的级别。不管是哪个线程创建了哪一个线程,进程内的任何线程都可以销毁、挂起、恢复和更改其它线程的优先权。线程也要对进程施加控制,进程中任何线程都可以通过销毁主线程来销毁进程,销毁主线程将导致该进程的销毁,对主线程的修改可能影响所有的线程。
7、子进程不对任何其他子进程施加控制,进程的线程可以对同一进程的其它线程施加控制。子进程不能对父进程施加控制,进程中所有线程都可以对主线程施加控制。
相同点:
进程和线程都有ID/寄存器组、状态和优先权、信息块,创建后都可更改自己的属性,都可与父进程共享资源、都不直接访问其他无关进程或线程的资源。
Not a Number
会输出 Number
可以实现将ES6编译为ES5代码
1.px:绝对单位,页面按精确像素展示
2.em:相对单位,基准点为父节点字体的大小,如果自身定义了font-size按自身来计算(浏览器默认字体是16px),整个页面内1em不是一个固定的值。
3.rem:相对单位,可理解为”root em”, 相对根节点html的字体大小来计算,CSS3新加属性,chrome/firefox/IE9+支持。
4.vw:viewpoint width,视窗宽度,1vw等于视窗宽度的1%。
5.vh:viewpoint height,视窗高度,1vh等于视窗高度的1%。
6.vmin:vw和vh中较小的那个。
7.vmax:vw和vh中较大的那个。
8.%:百分比
9.in:寸
10.cm:厘米
11.mm:毫米
12.pt:point,大约1/72寸
13.pc:pica,大约6pt,1/6寸
14.ex:取当前作用效果的字体的x的高度,在无法确定x高度的情况下以0.5em计算(IE11及以下均不支持,firefox/chrome/safari/opera/ios safari/android browser4.4+等均需属性加么有前缀)
15.ch:以节点所使用字体中的“0”字符为基准,找不到时为0.5em(ie10+,chrome31+,safair7.1+,opera26+,ios safari 7.1+,android browser4.4+支持)
a. 图片懒加载,滚动到相应位置才加载图片。
b. 图片预加载,如果为幻灯片、相册等,将当前展示图片的前一张和后一张优先下载。
c. 使用CSSsprite,SVGsprite,Iconfont、Base64等技术,如果图片为css图片的话。
d. 如果图片过大,可以使用特殊编码的图片,加载时会先加载一张压缩的特别厉害的缩略图,以提高用户体验。
1 shift() 删除并返回数组的第一个元素;如果数组为空则返回undefined
var a = [1,2,3,4,5];
console.log(a.shift());//1
console.log(a);//[2, 3, 4, 5]
2 unshift() 向数组的开头添加一个或更多元素,并返回新的长度。
var a = [1,2,3,4,5];
console.log(a.unshift(-2,-1));//7
console.log(a);//[-2, -1, 1, 2, 3, 4, 5]
3 pop() 删除并返回数组的最后一个元素;如果数组为空则返回undefined
var a = [1,2,3,4,5];
console.log(a.pop());//5
console.log(a);//[1, 2, 3, 4]
4 push() 向数组的末尾添加一个或更多元素,并返回新的长度。
var a = [1,2,3,4,5];
console.log(a.push(6,7));//7
console.log(a);//[1, 2, 3, 4, 5, 6, 7]
5 concat() 连接两个或更多的数组,并返回结果。
var a = [1,2,3,4,5];
console.log(a.concat(6,7));//[1, 2, 3, 4, 5, 6, 7]
console.log(a);//[1, 2, 3, 4, 5]
6 splice() 拼接 删除元素,并向数组添加新元素。返回被删除的项目。
arrayObject.splice(index,howmany,item1,…,itemX)
index 必需。整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置。
howmany 必需。要删除的项目数量。如果设置为 0,则不会删除项目。
item1, …, itemX 可选。向数组添加的新项目。
var a = [1,2,3,4,5];
console.log(a.splice(2,2,7,8,9));//[3, 4]
console.log(a);//[1, 2, 7, 8, 9, 5]
7 reverse() 颠倒数组中元素的顺序。返回颠倒后的数组。
var a = [1,2,3,4,5];
console.log(a.reverse());//[5, 4, 3, 2, 1]
console.log(a);//[5, 4, 3, 2, 1]
8 sort() 对数组的元素进行排序
arrayObject.sort(sortby) sortby 可选。规定排序顺序。必须是函数。
它的排序原理是每2个数比较,然后根据正负更改数组内元素的位置,正的话位置改变,负的话位置不变。
比如比较,a是888,b是2222然后返回888-2222 是负的 位置不变.
var a = [1,2,3,4,5];
console.log(a.sort());//[1, 2, 3, 4, 5]
console.log(a);//[1, 2, 3, 4, 5]
console.log(a.sort(function(a,b){ //[5, 4, 3, 2, 1]
return b-a;
}))
9 slice() 从某个已有的数组返回选定的元素组成的新数组
var a = [1,2,3,4,5];
console.log(a.slice(2,5));//[3, 4, 5]
console.log(a);//[1, 2, 3, 4, 5]
10 join() 把数组的所有元素放入一个字符串。元素通过指定的分隔符进行分隔。
var a = [1,2,3,4,5];
console.log(a.join("|"));//1|2|3|4|5
console.log(a);//[1, 2, 3, 4, 5]
定义特权方法 :在构造函数内部通过this关键字定义的的方法,可以被实例化的对象继承所调用。
var Student = function(name) {
var _name = name; //私有属性
//特权方法
this.getName = function() {
return _name;
};
this.setName = function(name) {
_name = name;
};
};
var s1 = new Student('zhangsan');
s1.getName(); //zhangsan
特权方法的作用
特权方法能够在构造函数外面公开访问(仅限于实例化的对象),而且还能够访问私有成员和方法,因此用来做为对象或者构造函数的接口最合适不过了,通过特权方法我们可以控制公有方法对私有属性或方法的访问。 在JS框架的扩展中有很多应用。
特权方法与公有方法的区别
相同点:1. 都可以在构造函数外部公开访问。2. 都可以访问公有属性
不同点:有2点
//创建Student对象实例
var s1 = new Student('zhangsan');
var s2 = new Student('lisi');
//两实例的特权方法的引用不相同, 说明在对象实例化的时特权方法被重新创建
console.log(s1.getName === s2.getName); //false
//为Student创建公有方法
//公有方法不能访问私有属性
Student.prototype.myMethod = function() {
console.log(_name); //ReferenceError: _name is not defined
};
s1.myMethod();
小结:特权方法作为构造函数的接口,公有方法可以通过特权方法访问私有属性和方法
(1)Object.assign(target,source1,source2,…)
该方法主要用于对象的合并,将源对象source的所有可枚举属性合并到目标对象target上,此方法只拷贝源对象的自身属性,不拷贝继承的属性。
Object.assign方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。同名属性会替换。
Object.assign只能进行值的复制,如果要复制的值是一个取值函数,那么将求值后再复制。
Object.assign可以用来处理数组,但是会把数组视为对象。
const target = {
x : 0,
y : 1
};
const source = {
x : 1,
z : 2 ,
fn : {
number : 1
}
};
Object.assign(target, source);
// target {x : 1, y : 1, z : 2, fn : {number : 1}} // 同名属性会被覆盖
// source {x : 1, z : 2, fn : {number : 1}}
target.fn.number = 2; // 拷贝为对象引用
// source {x : 1, z : 2, fn : {number : 2}}
function Person(){
this.name = 1
};
Person.prototype.country = 'china';
let student = new Person();
student.age = 29 ;
const young = {insterst : 'sport'};
Object.assign(young,student);
// young {instest : 'sport' , age : 29, name: 1} // 只能拷贝自身的属性,不能拷贝prototype
Object.assign([1, 2, 3], [4, 5]) // 把数组当作对象来处理
// [4, 5, 3]
(2)Object.create(prototype[,propertiesObject])
使用指定的原型对象及其属性去创建一个新的对象
var parent = {
x : 1,
y : 1
}
var child = Object.create(parent,{
z : { // z会成为创建对象的属性
writable:true,
configurable:true,
value: "newAdd"
}
});
console.log(child)
(3)Object.defineProperties(obj,props)
直接在一个对象上定义新的属性或修改现有属性,并返回该对象。
var obj = {};
Object.defineProperties(obj, {
'property1': {
value: true,
writable: true
},
'property2': {
value: 'Hello',
writable: false
}
// etc. etc.
});
console.log(obj) // {property1: true, property2: "Hello"}
(4)Object.defineProperty(obj,prop,descriptor)
在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。
Object.defineProperty(Object, 'is', {
value: function(x, y) {
if (x === y) {
// 针对+0 不等于 -0的情况
return x !== 0 || 1 / x === 1 / y;
}
// 针对NaN的情况
return x !== x && y !== y;
},
configurable: true,
enumerable: false,
writable: true
});
// 注意不能同时设置(writable,value) 和 get,set方法,否则浏览器会报错 : Invalid property descriptor. Cannot both specify accessors and a value or writable attribute
(5)Object.keys(obj)
返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for…in 循环遍历该对象时返回的顺序一致 (两者的主要区别是 一个 for-in 循环还会枚举其原型链上的属性)。
let arr = ["a", "b", "c"];
console.log(Object.keys(arr));
// ['0', '1', '2']
/* Object 对象 */
let obj = { foo: "bar", baz: 42 },
keys = Object.keys(obj);
console.log(keys);
// ["foo","baz"]
(6)Object.values()
方法返回一个给定对象自己的所有可枚举属性值的数组,值的顺序与使用for…in循环的顺序相同 ( 区别在于 for-in 循环枚举原型链中的属性 )。
Object.values会过滤属性名为 Symbol 值的属性。
var an_obj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.values(an_obj)); // ['b', 'c', 'a']
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.values(obj)); // ['a', 'b', 'c']
(7)Object.entries()
返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for…in 循环遍历该对象时返回的顺序一致(区别在于 for-in 循环也枚举原型链中的属性)。
const obj = { foo: 'bar', baz: 42 };
console.log(Object.entries(obj)); // [ ['foo', 'bar'], ['baz', 42] ]
const simuArray = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.entries(simuArray)); // [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ]
(8)hasOwnProperty()
判断对象自身属性中是否具有指定的属性。
obj.hasOwnProperty(‘name’)
(9)Object.getOwnPropertyDescriptor(obj,prop)
返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性).
如果指定的属性存在于对象上,则返回其属性描述符对象(property descriptor),否则返回 undefined。
const object1 = {
property1: 42
};
console.log(Object.getOwnPropertyDescriptor(object1, 'property1'));
(10)Object.getOwnPropertyDescriptors(obj)
获取一个对象的所有自身属性的描述符。
var obj = {
name : 'js',
age : 20
}
console.log(Object.getOwnPropertyDescriptors(obj))
输出:
(11)Object.getOwnPropertyNames()
返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。
var obj = { 0: "a", 1: "b", 2: "c"};
Object.getOwnPropertyNames(obj).forEach(function(val) {
console.log(val);
});
var obj = {
x : 1,
y : 2
}
Object.defineProperty(obj,'z',{
enumerable : false
})
console.log(Object.getOwnPropertyNames(obj)) // ["x", "y", "z"] 包含不可枚举属性 。
console.log(Object.keys(obj)) // ["x", "y"] 只包含可枚举属性 。
(12)Object.getOwnPropertySymbols()
返回一个给定对象自身的所有 Symbol 属性的数组。
(13)Object.getPrototypeOf()
返回指定对象的原型(内部[[Prototype]]属性的值,即__proto__,而非对象的prototype)。
const prototype1 = {};
const object1 = Object.create(prototype1);
console.log(Object.getPrototypeOf(object1));//{}
console.log(Object.getPrototypeOf(object1) === prototype1);//true
(14)isPrototypeOf()
判断一个对象是否存在于另一个对象的原型链上。
var p = {
x: 1
}; //定义一个原型对象
var o = Object.create(p); //使用这个原型创建一个对象
console.log(p.isPrototypeOf(o));//=>true:o继承p
console.log(Object.prototype.isPrototypeOf(p)); //=> true p继承自Object.prototype
(15)Object.setPrototypeOf(obj,prototype)
设置对象的原型对象
let proto = {};
let obj = {
x: 10
};
Object.setPrototypeOf(obj, proto);
proto.y = 20;
proto.z = 40;
console.log(obj.x); // 10
console.log(obj.y); // 20
console.log(obj.z); // 40
(16)Object.is()
判断两个值是否相同。
如果下列任何一项成立,则两个值相同:
两个值都是 undefined
两个值都是 null
两个值都是 true 或者都是 false
两个值是由相同个数的字符按照相同的顺序组成的字符串
两个值指向同一个对象
两个值都是数字并且
都是正零 +0
都是负零 -0
都是 NaN
都是除零和 NaN 外的其它同一个数字
Object.is('foo', 'foo'); // true
Object.is(window, window); // true
Object.is('foo', 'bar'); // false
Object.is([], []); // false
var test = { a: 1 };
Object.is(test, test); // true
Object.is(null, null); // true
// 特例
Object.is(0, -0); // false
Object.is(-0, -0); // true
Object.is(NaN, 0/0); // true
(17)Object.freeze()
冻结一个对象,冻结指的是不能向这个对象添加新的属性,不能修改其已有属性的值,不能删除已有属性,以及不能修改该对象已有属性的可枚举性、可配置性、可写性。也就是说,这个对象永远是不可变的。该方法返回被冻结的对象。
var obj = {
prop: function() {},
foo: 'bar'
};
// 新的属性会被添加, 已存在的属性可能
// 会被修改或移除
obj.foo = 'baz';
obj.lumpy = 'woof';
delete obj.prop;
// 作为参数传递的对象与返回的对象都被冻结
// 所以不必保存返回的对象(因为两个对象全等)
var o = Object.freeze(obj);
o === obj; // true
Object.isFrozen(obj); // === true
// 现在任何改变都会失效
obj.foo = 'quux'; // 静默地不做任何事
// 静默地不添加此属性
obj.quaxxor = 'the friendly duck';
console.log(obj)
(18)Object.isFrozen()
判断一个对象是否被冻结 .
(19)Object.preventExtensions()
对象不能再添加新的属性。可修改,删除现有属性,不能添加新属性。
var obj = {
name :'lilei',
age : 30 ,
sex : 'male'
}
obj = Object.preventExtensions(obj);
console.log(obj); // {name: "lilei", age: 30, sex: "male"}
obj.name = 'haha';
console.log(obj) // {name: "haha", age: 30, sex: "male"}
delete obj.sex ;
console.log(obj); // {name: "haha", age: 30}
obj.address = 'china';
console.log(obj) // {name: "haha", age: 30}
(20)Object.isExtensible()
判断对象是否是可扩展的,Object.preventExtensions,Object.seal 或 Object.freeze 方法都可以标记一个对象为不可扩展(non-extensible)
(21)Object.seal()
Object.seal() 方法可以让一个对象密封,并返回被密封后的对象。密封一个对象会让这个对象变的不能添加新属性,且所有已有属性会变的不可配置。属性不可配置的效果就是属性变的不可删除,以及一个数据属性不能被重新定义成为访问器属性,或者反之。但属性的值仍然可以修改。尝试删除一个密封对象的属性或者将某个密封对象的属性从数据属性转换成访问器属性,结果会静默失败或抛出TypeError 异常. 不会影响从原型链上继承的属性。但 proto ( ) 属性的值也会不能修改。
(22)Object.isSealed()
判断一个对象是否被密封