var scope = 'top';
var f1 = function() {
console.log(scope);
};
f1(); // 输出 top
var f2 = function() {
var scope = 'f2';
f1();
};
f2(); // 输出 top
复制代码
当一个函数返回它内部定义的一个函数时,就产生了一个闭包, 闭包不但包括被返回的函数,还包括这个函数的定义环境node
var generateClosure = function() {
var count = 0;
var get = function() {
count ++;
return count;
};
return get;
};
var counter1 = generateClosure();
var counter2 = generateClosure();
console.log(counter1()); // 输出 1
console.log(counter2()); // 输出 1
console.log(counter1()); // 输出 2
console.log(counter1()); // 输出 3
console.log(counter2()); // 输出 2
复制代码
上面这个例子解释了闭包是如何产生的:counter1 和 counter2 分别调用了 generate- Closure() 函数,生成了两个闭包的实例,它们内部引用的 count 变量分别属于各自的 运行环境。咱们能够理解为,在 generateClosure() 返回 get 函数时,私下将 get 可 能引用到的 generateClosure() 函数的内部变量(也就是 count 变量)也返回了,并在内存中生成了一个副本,以后 generateClosure() 返回的函数的两个实例 counter1 和 counter2 就是相互独立的了。数组
var generateClosure = function() {
var count = 0; //私有变量
var get = function() {
count ++;
return count;
};
return get;
};
var counter = generateClosure();
console.log(counter()); // 输出 1
console.log(counter()); // 输出 2
console.log(counter()); // 输出 3
复制代码
在函数中经过返回一个子函数,对外部暴露一个访问和更新内部变量的接口,外部不能直接访问函数做用域内的变量,完成了对变量私有化的隐藏浏览器
上下文对象就是 this 指针,即被调用函数所处的环境闭包
JavaScript 的任何函数都是被某个对象调用的,在最外部全局做用域中,调用它的是全局对象app
this 指针不属于某个函数,而是函数调用时所属的对象。也就是说谁调用的函数,this就指向谁函数
var someuser = {
name: 'Tom',
func: function() {
console.log(this.name);
}
};
var foo = {
name: 'foobar'
};
someuser.func(); // 输出 Tom
foo.func = someuser.func;
foo.func(); // 输出 foobar
name = 'global';
func = someuser.func;
func(); // 输出 global
复制代码
在 JavaScript 中,本质上,函数类型的变量是指向这个函数实体的一个引用,在引用之间赋值不会对对象产生复制行为。咱们能够经过函数的任何一个引用调用这个函数,不一样之处仅仅在于上下文ui
使用原型和构造函数初始化对象属性的区别:this
//原型方式
function Person() {
}
Person.prototype.name = 'Tom';
Person.prototype.showName = function () {
console.log(this.name);
};
var person = new Person();
person.showName();
//构造函数方式
function Person(){
this.name = 'Tom';
this.showNmae = function(){
console.log(this.name);
}
}
var person = new Person();
person.showName();
复制代码
function Foo() {
}
Object.prototype.name = 'My Object'; Foo.prototype.name = 'Bar';
var obj = new Object();
var foo = new Foo();
console.log(obj.name); // 输出 My Object
console.log(foo.name); // 输出 Bar
console.log(foo.__proto__.name); // 输出 Bar
console.log(foo.__proto__.__proto__.name); // 输出 My Object
console.log(foo. __proto__.constructor.prototype.name); // 输出 Bar
复制代码
平常开发中,若是只须要复制基本的属性时(基本类型、对象、数组等,不包含函数与特殊对象new Date()、正则等),使用JSON序列化再反序列化的方法是最便捷的方式spa
JSON.parse(JSON.stringify(obj))
复制代码
Object.prototype.clone = function() {
var newObj = {};
for (var i in this) {
if (typeof(this[i]) == 'object' || typeof(this[i]) == 'function') {
newObj[i] = this[i].clone();
} else {
newObj[i] = this[i];
} }
return newObj;
};
Array.prototype.clone = function() {
var newArray = [];
for (var i = 0; i < this.length; i++) {
if (typeof(this[i]) == 'object' || typeof(this[i]) == 'function') {
newArray[i] = this[i].clone();
} else {
newArray[i] = this[i];
} }
return newArray;
}
Function.prototype.clone = function () {
var that = this;
var newFun = function newFun() {
return that.apply(this, arguments); //这里构成了闭包
};
for (var i in this) {
newFun[i] = this[i];
}
return newFun;
}
复制代码
WeakMap对象是一组键/值对的集合,其中的键是弱引用的。其键必须是对象,而值能够是任意的 遍历对象时使用WeakMap结构存储,遇到循环引用的对象,经过WeakMap.prototype.has(key)与WeakMap.prototype.get(key)来终止循环遍历问题prototype
function isObj(obj) {
return (typeof obj === 'object' || typeof obj === 'function') && obj !== null
}
function deepCopy(obj, mapObj = new WeakMap()) {
if(mapObj.has(obj)) return mapObj.get(obj)
let cloneObj = Array.isArray(obj) ? [] : {}
mapObj.set(obj, cloneObj)
for (let key in obj) {
cloneObj[key] = isObj(obj[key]) ? deepCopy(obj[key], mapObj) : obj[key];
}
return cloneObj
}
复制代码