1.Object.create的模擬javascript
//Object.create 該方法是ES5新增的方法,因此IE8以前不支持
html
function create(obj){
java
function F(){}
面試
F.prototype=obj;
數組
return new F();
瀏覽器
}
函數
var obj={
工具
val:1
測試
};
this
var o=create(obj);
console.log(o.val);//1
</script>
2.create兼容性處理
<script>
//兼容IE8,若是瀏覽器Object上沒有create方法,
//那麼本身添加一個模擬的
if(!Object.create){
Object.create=function(obj){
function F(){}
F.prototype=obj;
return new F();
}
}
//說明,若是瀏覽器支持Object.create方法,則優先使用Object.create方法
//若是不支持,則本身實現一個相似的方法,可是不保證和Object.create一致
function create (obj){
if(Object.create){
Object.create(obj);
}else{
function F(){}
F.prototype=obj;
return new F();
}
}
</script>
3.函數的原型鏈
<script>
//全部的函數都直接繼承Function.prototype
//1.函數有兩個原型相關的屬性
function fn(){}
//構造函數fn==>Function.prototype==>Object.prototype==>null
//構造函數的原生對象fn.prototype==>Object.prototype==>null
//Array==>Function.prototype==>Object.prototyp==>null
//Array.prototype==>Object.prototype==>null
//Function==>Function.prototype==>Object.prototype==>null
//Function.prototype==>Object.prototype==>null
//Object==>Function.prototype==>Object.prototype==>null
//Object.prototype==>null
</script>
4.copy繼承與對象回收的問題
<script>
function extend(o,o2){
for(var key in o2){
o[key]=o2[key];
}
}
//obj指向的對象,只要被obj變量或其餘變量或其餘屬性引用着
//那麼obj指向的那個對象永遠不會被垃圾回收機制回收掉
var obj={
val:1
};
var o=new Object();
extend(o,obj);//obj自身沒有任何改變
obj=null;
//這時候,obj以前指向的那個對象,沒有任何變量或者屬性引用它了
//那麼這個對象未來就會被回收
var o2={
a:1
};
//吧一個字面量對象的屬性copy到o2裏面,copy完畢以後
//這個字面量對象並無任何變量或屬性引用他
//那麼這個字面量對象未來就會被釋放掉
extend(o2,{
b:2
});
</script>
5.關於對象的類型
<script>
/*
* 全部的數組都是Array類型;
* 全部的函數都是Function類型;
* 全部的日期都是Date類型。
* */
</script>
6.instanceof
<script>
//instanceof 是誰的實例
//做用:判斷一個對象是否是另外一個構造函數的實例
//語法: 對象 instanceof 構造函數
function Dog(){}
var beibei=new Dog();
//beibei是Dog的實例
//beibei==>Dog.prototype(Dog構造函數原生的原型對象)==>Object.prototype==>null
//這個原生的原型對象在beibei的原型鏈結構中存在
console.log(beibei instanceof Dog);//true
Dog.prototype={
run:function(){
console.log('跑');
}
}
//beibei==>Dog.prototype(Dog構造函數原生的原型對象)==>Object.prototype==>null
//Dog.prototype如今存儲的是自定義的原型對象
//這個自定義的原型對象不在beibei的原型鏈結構中
console.log(beibei instanceof Dog);//false
beibei.run();//報錯 不能再建立對象實例以後定義函數
//由於實例繼承的仍然是原生的原型對象
//發現剛開始是true,後面修改了構造函數的原型屬性後
//結果是false,說明instanceof運算符實力很深
//instanceof運算符的運算規則:
//判斷左邊對象的原型鏈結構中,是否存在右邊構造函數的顯示原型對象
</script>
7.instanceof面試題
<script>
//函數的原型鏈結構
//Function==>Function.prototype==>Object.prototype==>null
console.log(Function instanceof Function);//true
console.log(Function instanceof Object);//true
//Object的原型鏈結構
//Object==>Function.prototype==>Object.prototype==>null
console.log(Object instanceof Function);//true
console.log(Object instanceof Object);//true
// 自定義構造函數系列的面試題
function Dog(){}
var beibei=new Dog();
console.log(beibei instanceof Dog);//true
Dog.prototype={};
console.log(beibei instanceof Dog);//false
// 內置的構造函數系
var arr=[];
console.log(arr instanceof Array);//true
console.log(arr instanceof Function);//false
console.log(arr instanceof Object);//true
console.log(Object.prototype instanceof Object);//false
// 這個是false,即Object.prototype繼承的是null;
// 和Object的顯式原型對不上。
instanceOf考題
<script>
//copy函數
function extend(obj1,obj2){
for(var key in obj2){
obj1[key]=obj2[key];
}
}
//考題1系列
function Person(){}
//給原生原型添加一個屬性
Person.prototype.eat='吃';
var zs=new Person();
console.log(zs instanceof Person); //true
console.log(zs instanceof Function); //false
console.log(zs instanceof Object);//true
// zs==>person.prototype==>object.prototype==>null
// 考題2系列
// 覆寫原生原型對象
Person.prototype = {
run: '跑'
};
var xgl = new Person();
console.log(zs instanceof Person); //false
console.log(xgl instanceof Person); //true
//xgl==>person.prototype==>object.prototype==>null
// console.log(xgl);
// 考題3系列
function Student() {}
var zj = new Student();
extend(Student.prototype, Person.prototype);
//zj==>Student.prototype==>object.prototype==>null
// console.log(zj);
console.log(zj instanceof Student); //true
console.log(zj instanceof Person); //false
console.log(zs instanceof Student); //false
console.log(zs instanceof Person); //false
console.log(xgl instanceof Student); //false
console.log(xgl instanceof Person); //true
var sl = new Student();
console.log(sl instanceof Student); //true
console.log(sl instanceof Person); //false
//sl==>Student.prototype==>object.prototype==>null
console.log(sl);
// 考題4系列
var ll = Object.create(Student.prototype);
//ll==>Student.prototype==>object.prototype==>null
// console.log(ll);
console.log(ll instanceof Student); //true
console.log(ll instanceof Person); //false
// 考題5系列
Student.prototype = new Person();
var tj = new Student();
//tj==>Student.prototype==>object.prototype==>null
// console.log(tj);
console.log(ll instanceof Student); //false
console.log(ll instanceof Person); //false
console.log(tj instanceof Student); //true
console.log(tj instanceof Person); //true
// 考題6系列
// new Date ==>Date.prototype==>Object.prototype==>null
console.log(new Date instanceof Function); //false
console.log(new Date instanceof Object); //true
// new Function ==>Function.prototype==>Object.prototype==>null
console.log(new Function instanceof Function); //true
console.log(new Function instanceof Object); //true
// Number ==>Function.prototype==>Object.prototype==>null
console.log(Number instanceof Function); //true
console.log(Number instanceof Object); //true
// Function ==>Function.prototype==>Object.prototype==>null
console.log(Function instanceof Function); //true
console.log(Function instanceof Object); //true
// Object ==>Function.prototype==>Object.prototype==>null
console.log(Object instanceof Function); //true
console.log(Object instanceof Object); //true
</script>
</script>
老師給出的答案 詳細解釋(instanceof 考題)
<script>
// copy函數
function extend(obj1, obj2) {
for(var key in obj2) {
obj1[key] = obj2[key];
}
}
// 考題1系列
console.log('------------------1-----------------');
function Person() {}
// 給原生原型添加一個屬性
Person.prototype.eat = '吃';
var zs = new Person();
console.log(zs instanceof Person); // true
console.log(zs instanceof Function); // false
console.log(zs instanceof Object); // true
// zs ==> Person.prototype(原生的原型對象) ==> Object.prototype ==> null
// 考題2系列
// 覆寫原生原型對象
console.log('------------------2-----------------');
Person.prototype = {
run: '跑'
};
var xgl = new Person();
console.log(zs instanceof Person); // false
console.log(xgl instanceof Person); // true
// xgl ==> Person.prototype(自定義的原型對象) ==> Object.prototype ==> null
// 考題3系列
console.log('------------------3-----------------');
function Student() {}
var zj = new Student();
extend(Student.prototype, Person.prototype);
// zs ==> Person.prototype(原生的原型對象) ==> Object.prototype ==> null
// xgl ==> Person.prototype(自定義的原型對象) ==> Object.prototype ==> null
// zj ==> Student.prototype(原生的原型對象)==> Object.prototype ==> null
console.log(zj instanceof Student); // true
console.log(zj instanceof Person); // false
console.log(zs instanceof Student); // false
console.log(zs instanceof Person); // false
console.log(xgl instanceof Student); // false
console.log(xgl instanceof Person); // true
var sl = new Student();
console.log(sl instanceof Student); // true
console.log(sl instanceof Person); // false
// sl ==> Student.prototype(原生的原型對象)==> Object.prototype ==> null
// 考題4系列
console.log('------------------4-----------------');
var ll = Object.create(Student.prototype);
// ll ==> Student.prototype(原生的原型對象)==> Object.prototype ==> null
console.log(ll instanceof Student); // true
console.log(ll instanceof Person); // false
// 考題5系列
console.log('------------------5-----------------');
Student.prototype = new Person();
var tj = new Student();
// ll ==> Student.prototype(原生的原型對象)==> Object.prototype ==> null
// tj ==> Student.prototype(Person的實例) ==> Person.prototype(自定義的原型對象) ==> Object.prototype ==> null
console.log(ll instanceof Student); // false
console.log(ll instanceof Person); // false
console.log(tj instanceof Student); // true
console.log(tj instanceof Person); // true
// 考題6系列
console.log('------------------6-----------------');
// new Date ==> Date.prototype ==> Object.prototype ==> null
console.log(new Date instanceof Function); // false
console.log(new Date instanceof Object); // true
// new Function ==> Function.prototype ==> Object.prototype ==> null
console.log(new Function instanceof Function); // true
console.log(new Function instanceof Object); // true
// Number ==> Function.prototype ==> Object.prototype ==> null
console.log(Number instanceof Function); // true
console.log(Number instanceof Object); //true
// Function ==> Function.prototype ==> Object.prototype ==> null
console.log(Function instanceof Function); // true
console.log(Function instanceof Object); // true
// Object ==> Function.prototype ==> Object.prototype ==> null
console.log(Object instanceof Function); // true
console.log(Object instanceof Object); // true
</script>
8.Object原型上的方法介紹
<script>
//Object.prototype原型上的方法:
//這些方法,全部擁有原型鏈結構的對象都能使用
//hasOwnProperty
//for in
//isPrototypeOf
//propertyIsEnumerable
//toLocaleString
//toString
//valueOf
//1.hasOwnProperty has有 own本身的 property 屬性
//方法的做用:判斷一個屬性是否是本身的(判斷本身有沒有某個屬性)
//上訴語言中的本身,指的是調用hasOwnProperty的那個對象
//語法:對象.hasOwnProperty(屬性名)
var obj={
val:1
};
console.log(obj.hasOwnProperty('val'));//true
//val是obj對象本身的屬性,因此結果爲true
console.log(obj.hasOwnProperty('toString'));//false
//toString不是obj對象本身的屬性,因此結果爲false
//自定義的屬性是可枚舉的,可以被for in遍歷出來
//內置的屬性是不可枚舉的,不可以被for in遍歷出來
function extend(o,o2){
for(var key in o2){
//for in能夠把一個對象繼承的屬性給遍歷出來
if(o2.hasOwnProperty(key)){
//若是是本身的屬性,才copy到第一個對象中
o[key]=o2[key];
}
}
}
Object.prototype.itcast='傳智播客';
var obj={
val:100
};
var o={};
//把obj對象本身的屬性copy到o中
extend(o,obj);
console.log(o);//object{val:100}
console.log(obj);//object{val:100}
console.log(o.itcast);//傳智播客 可是o也能夠訪問itcast屬性
// ——————————————————————————————————————————————————--
//2.for in 遍歷對象的屬性,它不光能夠遍歷該對象本身的屬性
//還能遍歷這個對象所繼承的屬性
//固然必須知足一個條件,(這些必須是可枚舉的)
Array.prototype.it='IT';
Object.prototype.itcast='itcast';
var arr=[];
for(var key in arr){
console.log(key);//it和itcast都能打印出來
}
// ..............................................
//3.isPrototypeOf
//is是 prototype 原型 of 誰的
//該方法的做用:判斷調用isprototypeOf方法的對象,在不在另外一個對象的原型鏈中
//這個方法和instanceof有點相似,都和原型鏈相關,不過他們的語法規則相差很大
//語法:對象.isPrototypeOf(另外一個對象)
var arr=[];
console.log(Array.prototype.isPrototypeOf(arr));//true
//Array.prototype這個對象在arr的原型鏈中,因此結果爲true
/*---------------------------------------------------------*/
//4.propertyIsEnumerable
//property屬性 is是 enumerable枚舉
//該方法的做用:判斷一個屬性是否是可枚舉的,又判斷這個屬性是否是本身的
//因此該方法通常解釋爲是hasOwnProperty的增強版本
//語法: 對象.propertyIsEnumerable(屬性名)
var o={
a:1
};
Object.prototype.it='IT';
console.log(o.propertyIsEnumerable('a'));//true
console.log(o.propertyIsEnumerable('it'));//false
console.log(o.hasOwnProperty('a'));//true
console.log(o.hasOwnProperty('it'));//false
console.log(Object.prototype.propertyIsEnumerable('it'));//true
console.log(Object.prototype.propertyIsEnumerable('toString'));//false
console.log(Object.prototype.hasOwnProperty('it')); // true
console.log(Object.prototype.hasOwnProperty('toString')); // true
/*---------------------------------------------------------*/
//5.toLocalString
//做用:根據對象的類型,調用該對象本地的toString方法
//arr==>Array.prototype==>Object.prototype==>null
var arr=[1,2,3];
//由於Array.prototype上面存在toLocalString這個方法
//爲了可以讓arr調用Object.prototype上面的toLocalString這個方法
//因此手動的把Object.prototype上面的toLocaleString這個方法添加到arr自身。
arr.toLocaleString=Object.prototype.toLocaleString;
console.log(arr.toLocaleString());//1,2,3
console.log(arr.toString());//1,2,3
/*---------------------------------------------------------*/
//6.toString
//不一樣的構造函數 .prototype都有屬於本身的toString方法
//這裏說的是Object.prototype上的toString
//做用:返回一個相似於這樣的字符串'[object 類型名]'
//這個字符串中包含了對象的類型(通常用來區分ECMAScript內置的10大對象類型)。
//打印'[object object]'
var obj={};
console.log(obj.toString());//[object object]
//打印'[object Array]'
var arr=[];
arr.toString=Object.prototype.toString;
console.log(arr.toString());//[object Array]
// 打印'[object Date]'
var date=new Date();
date.toString=Object.prototype.toString;
console.log(date.toString());//[object Date]
// 打印'[object Math]'
console.log(Math.toString());//[object Math]
// 打印'[object Boolean]'
var boo = new Boolean();
boo.toString = Object.prototype.toString;
console.log(boo.toString());//[object Boolean]
// 打印'[object HTMLBodyElement]'
document.body.toString = Object.prototype.toString;
console.log(document.body.toString());//[object HTMLBodyElement]
// 打印'[object Object]'
function Dog() {}
var gougou = new Dog();
console.log(gougou.toString());
// 根據上訴測試,發現Object.prototype上的toString能夠用來獲取內置對象的類型。
/*---------------------------------------------------------*/
//7.value of
做用:返回對象自身
console.log(obj.valueOf());//Object{}
console.log(obj===obj.valueOf());//true
</script>
9.靜態成員和實例成員
<script>
//1.靜態成員(類成員):
//添加到構造函數身上的屬性或者方法,能夠稱之爲靜態成員
//通常添加到構造函數身上的方法,都是工具性方法
// 函數也是對象,對象不必定是函數。
// 數組也是對象,對象不必定是數組。
// 對象是泛指,函數和數組是對象具體的類型。
function Person(){
// 表明某個實例本身的最大年齡
this.MAX_AGE=230;
}
Person.MAX_AGE=300;
// 靜態成員的特色,不用建立實例,就能夠訪問這個屬性。
console.log(Person.MAX_AGE);//300
//通常添加到構造函數身上的方法,都是工具性方法
Person.extend=function(obj){
for(var key in obj){
this[key]=obj[key];
}
}
// ..................................................
//2.實例成員
//添加給實例的屬性和方法就叫實例成員
//供實例使用的屬性和方法也叫實例成員
function Dog(name,age){
// 這是添加給未來的實例的,那麼這就是實例成員
this.name=name;
this.age=age;
}
// 這是添加給Dog本身的,實例不能使用,那麼這就是靜態成員。
Dog.MAX_AGE=24;
// 這是供實例使用的方法,那麼這也是實例成員
Dog.prototype.run=function(){
console.log('跑');
}
</script>
10.函數的屬性
<script>
//函數默認自有的一些屬性
//1.prototype:爲了讓實例繼承的對象
//2.__proto__:函數本身繼承的對象
//3.name:函數的名字,若是是匿名函數,那麼值是一個空字符串
//4.arguments:一個表明實參的對象,這個屬性會在函數被調用時從新賦值
//5.length:函數形參的個數
//6.caller:調用該函數的函數,這個屬性會在函數被調用時從新賦值
/*---------------------------length屬性------------------------*/
函數的length屬性:用來獲取形參的個數
function f(){}
console.log(f.length);//0
function f2(a,b){}
console.log(f2.length);//2
arguments的length屬性:用來獲取傳入的實參的個數
function count(a,b){
if(arguments.length<count.length){
throw'生氣了,爲何不給我傳入要求的參數';
}
console.log(a+b);
}
count(1,2);//3
// count(1);報錯 11函數的屬性.html:27 Uncaught 生氣了,爲何不給我傳入要求的參數 這是咱們手動添加的報錯
/*-----------------------------arguments屬性----------------------*/
function fn(){
// 這種方式淘汰了
console.log(fn.arguments);//[1,2]
// 這種是經常使用的方式,arguments後來被提高爲關鍵字了,能夠直接使用
console.log(arguments);//[1,2]
}
fn(1,2);
/*-----------------------------arguments的callee屬性----------------------*/
//arguments.callee屬性,返回被調用的函數自身
function add(){
//返回add自身
console.log(arguments.callee);// function add(){//返回add自身console.log(arguments.callee);}
}
add();
//callee通常用在匿名函數的遞歸裏
(function(){
//調用本身
arguments.callee();
})();
/*-----------------------------caller屬性----------------------*/
function f3(){
// 返回調用個人那個函數
console.log(f3.caller);//null 由於調用f3的是window 但window不是函數 因此值爲null
}
!function fff() {
// 返回調用個人那個函數,若是調用個人不是函數,那麼就返回null
console.log(fff.caller);// function fff() {// 返回調用個人那個函數,若是調用個人不是函數,那麼就返回nullconsole.log(fff.caller);f3();}
f3();
}();
//!()表示函數自調
</script>
11.in 運算符
<script>
//in運算符單獨使用時,能夠用來判斷對象可以使用某屬性
//單獨使用和枚舉沒有關係了,就看對象能不能使用某個屬性
//屬性名 in 對象
var o={
val:100
};
Object.prototype.itcast='czbk';
console.log('val'in o);//true
console.log('itcast' in o);//true
console.log('toString' in o);//true
</script>
12.delete運算符
<script>
//delete能夠用來刪除對象的屬性
//語法:delete 對象.屬性名
//語法:delete 對象[屬性名]
//delete能夠刪除一些全局屬性或方法,例如delete window.alert //delete也能夠刪除沒有經過var定義的全局變量 //經過var定義的全局變量沒法刪除
var o={
a:1,
b:2
};
console.log(o);//Object {a: 1, b: 2}
console.log(o.a);//1
console.log(o.b);//2
//刪除o的a屬性
delete o.a;
console.log(o.a);//undefined
console.log(o);//Object {b: 2}
delete o['b'];//也能夠用這種方式刪除,但要給裏面的屬性名加單引號,要否則就成了變量
console.log(o.b);
//刪除o的b屬性
delete o.b;
console.log(o.b);//undefined
console.log(o);//Object {}
</script>
13.Function&eval
<script id="jsTem" type="liubei">
var a = 1;
console.log(a);
</script>
<script >
//正常狀況下,<script type="javascript">
// var a=1;
// console.log(a);//1
//可是咱們若是修改script裏面的type屬性
//即 <script id="jsTem" type="liubei">
//此時j就不能在打印
// var a=1;
// console.log(a);
// Function 是一個內置的構造函數,能夠用來建立函數
// 語法:new function(arg1,arg2,arg3...,)
// 參數所有都是字符串
//這種方式至關於下面的方式,可是這種方式比較簡單便捷
// function cound(a,b){
// console.log(a+b);
// }
//用new是正常的使用方式
var fn=new Function('a','b','console.log(a+b);');
fn(1,2)//3
//不用new也ok
var fn2=Function('a','b','console.log(a+b);');
fn(10,20);//30
//Function能夠把字符串轉換爲函數的代碼體
//這樣就能夠經過Function執行字符串代碼
var jsTem=document.getElementById('jsTem').innerHTML;
Function(jsTem)();//1
//eval,也能夠執行字符串代碼,相比Function比較直接
//由於傳入eval的字符串會立刻執行,而Function先返回給你一個函數
//須要你手動調用一下才會執行
eval(jsTem);//1
eval('console.log(10)');//10
eval('console.log(103)')//103