**
1.JS繼承機制** 構造函數中的屬性和方法是不共享的,而爲了共享一些屬性和方法,也爲了避免浪費資源,出現了prototype,掛在prototype上的屬性和方法是共享的。javascript
function Ani(name) {
this.name = name;
// this.act = '叫';
}
var dog = new Ani('狗');
var cat = new Ani('貓');
// dog.act = '旺旺'; //只修改了dog的act屬性 不會影響cat的act屬性
Ani.prototype.act = '旺旺';
console.log(dog.name, dog.act, cat.name, cat.act);java
由此想到原型鏈繼承: _題目:_用原型鏈的方式實現繼承。建立一個基類PeoClass,其中有兩個公開方法:eat、sleep, 再建立一個子類EngiClass, eat繼承基類,重寫sleep方法:windows
function PeoClass() {
}
PeoClass.prototype = {
eat: function() {
},
sleep: function() {
}
}
function EngiClass() {
}
EngiClass.prototype = new PeoClass();
EngiClass.prototype.constructor = EngiClass;
EngiClass.prototype.sleep= function() {
// 重寫
}數組
2.關於深拷貝閉包
function deepClone(obj){
var newObj = obj instanceof Array ? [] : {};
for(var i in obj){
newObj[i] = typeof obj[i] == 'object'? deepClone(obj[i]) : obj[i];
}
return newObj;
}
app
3.關於數組 (1)數組去重dom
function norepeat(arr) {
var new_arr = [];
var obj = {};
for(var i = 0, len = arr.length; i < len; i ++) {
if(!obj[arr[i]]) {
obj[arr[i]] = arr[i];
new_arr.push(i);
}
}
return new_arr;
}
123456789101112函數
(2)數組排序/亂序this
function arrRand(arr) {
arr.sort(function() {
return 0.5 - Math.random();
});
}spa
(3)出現次數
function showCount(param) {
param = typeof param == 'string' ? param.split('') : param;
var obj = {};
for(var i = 0, len = param.length; i < len; i ++) {
if(!obj[param[i]]) {
obj[param[i]] = 1;
}else {
obj[param[i]] += 1;
}
}
return obj;
}
4.關於做用域、閉包以及this _做用域_:javascript是基於詞法做用域的語言,也就是靜態做用域,即在函數定義時就肯定了做用域,而不是執行時 _閉包:_兩個函數中間包裹一塊沒法直接訪問的做用域,只能經過間接地方式訪問;閉包可使內部變量始終保存在內存中;有閉包就可能形成內存泄漏。
function f1() {
var n = 99;
add = function() {
n += 1;
}
function f2() {
console.log(n);
}
return f2;
}
var res = f1();
res(); // 99
add();
res(); // 100 n一直保持在內存中
//
var x = 20;
var a = {
x: 15,
fn: function() {
var x = 30;
return function() {
return x;
};
}
}
console.log(a.fn());// function() {return x}
console.log(a.fn()());// 30
console.log((a.fn())());// 30
console.log((a.fn())() == a.fn()());// true
console.log(a.fn().call(this));//
console.log(a.fn().call(a)); //
_關於this:_動態綁定,也就是在函數執行時從上下文中獲取指向,上下文不一樣,this指向不一樣;通常指向調用者對象,也就是函數的擁有者;特殊的狀況是自執行函數,this指向window;(閉包趕上this時,要注意運行時的上下文,看栗子)(當構造函數中return一個對象(除了null)時,this指向return的對象)
var x = 'windows';
var obj_a = {
x: 1,
y: {
x: 2,
y: function() {
return function() {
return this.x;
}
},
z: function() {
return this.x;
}
}
}
var fun = obj_a.y.y();
console.log(obj_a.y.z()); // 2
console.log(obj_a.y.y()()); // windows
console.log(fun()); // 'windows'
4.關於call/apply/bind
var obj = {
a: 'obj.a',
b: function() {
console.log(this.a);
}
}
var fun = obj.b;
fun(); // undefined 由於執行時上下文中的this指向window
obj.b(); // 'obj.a' 執行時上下文中的this指向obj
_call_:改變對象的環境,即改變this指向,並調用函數;參數:n個,第一個參數是目標對象或者對象自己,其餘參數能夠是原函數的參數; 上述fun()語句若改成apply
fun.call(obj);//'obj.a'上下文中本來指向window的this強制指向了obj對象
_apply_:與call方法相似,效果也相似,只是參數格式不一樣,第一個參數都是目標對象或對象自己,但第二個參數必須是個數組,放置函數的參數
注意:非嚴格模式下,若call/apply的第一個參數傳入null、undefined, 則this指向window對象
_bind_:與以上兩個方法有些不一樣,可是都能改變this指向,不一樣之處在於bind方法並不能調用原函數,而是返回一個修改後的函數,稱爲綁定函數,若要執行須要手動調用該函數;
fun.bind(obj)(); // 'obj.a'
一樣bind也能夠有多個參數,格式能夠與call同樣,也能夠執行時再次添加
var a = { x: 'mx', y: function(a, b) { console.log(this.x); console.log(a+b); }}var b = a.y;b.call(a, 1, 2); // mx 3b.apply(a, [1, 2]); // mx 3b.bind(a, 1, 2)() // mx 3b.bind(a, 1)(2) // mx 3