摘要:對構(gòu)造函數(shù)使用運算符,就能生成實例,并且變量會綁定在實例對象上。這個對象的所有屬性和方法,都會被構(gòu)造函數(shù)的實例繼承。
對象 對象的含義
所謂對象,就是一種無序的數(shù)據(jù)集合,由若干個“鍵值對”(key-value)構(gòu)成。
對象的創(chuàng)建
使用new運算符創(chuàng)建Object
var p = new Object(); p.name = "Tony";
使用對象字面量的形式
//對象字面量形式 var p ={ name: "tony", work: function(){ console.log("working...."); }, _age: 18, get age(){ return this._age; }, set age(val){ if( val <0 || val > 150){ throw new Error("invalid value"); }else{ this._age = val; } } } console.log(p.name);對象的基本操作
成員屬性的添加
// Object.defineProperty()方法 Object.defineProperty(p, "age",{value: 18, writable: false}); //Object.defineProperties()方法 添加多個屬性 Object.defineProperties(p, { salary:{ value: 1000, writable: false }, gender:{ value: true } });
成員的遍歷
使用 for..in語句
Object.keys()方法 返回一個包含對象鍵名的字符串?dāng)?shù)組
var o ={}; o.name = "jack"; o.age = 20; for(var i in o){ console.log(o[i]); } // jack, 20 Object.keys(o); // ["name", "age"]
檢查對象是否有某個屬性
in 操作符
Object.hasOwnProperty()方法
var o = {name: "mariya"} "name" in o; // true o.hasOwnProperty("name"); // true
得到對象的屬性特性描述
Object.getOwnPropertyDescriptor(obj,property)
Object.getOwnPropertyDescriptor(o, "name"); //Object {value: "mariya", writable: true, enumerable: true, configurable: true}
刪除屬性
delete運算符,但有些對象的屬性是刪除不了的
delete o.name; //true o.name; // undefined成員特性
configurable 是否可設(shè)置
writable 是否可修改
enumerable 是否可枚舉
value屬性的值
var person ={}; Object.defineProperties(person,{ title: {value: "fe",enumerable: true}, age: {value: 19, enumerable: true, writable: true} }); Object.getOwnPropertyDescriptor(person,"title"); // Object {value: "fe", writable: false, enumerable: true, configurable: false} Object.getOwnPropertyDescriptor(person,"age"); // Object {value: 19, writable: true, enumerable: true, configurable: false}Constructor屬性
constructor始終指向創(chuàng)建當(dāng)前對象的構(gòu)造函數(shù)。
var arr = []; console.log(arr.constructor === Array); // true var Foo = function() {}; console.log(Foo.constructor === Function); // true // 由構(gòu)造函數(shù)實例化一個obj對象 var obj = new Foo(); console.log(obj.constructor === Foo); // true console.log(obj.constructor.constructor === Function); // true
每個函數(shù)都有一個默認的屬性prototype,而這個prototype的constructor默認指向這個函數(shù)。
function Person(name) { this.name = name; }; Person.prototype.getName = function() { return this.name; }; var p = new Person("jack"); console.log(p.constructor === Person); // true console.log(Person.prototype.constructor === Person); // true console.log(p.constructor.prototype.constructor === Person); // true類的創(chuàng)建
雖然js是門基于對象的語言,但是沒有類這一概念的,雖然保留了class的關(guān)鍵字,但在ES6之前是無法使用的。所以,可以用構(gòu)造函數(shù)模擬類的創(chuàng)建,也就是偽類。
所謂"構(gòu)造函數(shù)",其實就是一個普通函數(shù),但是內(nèi)部使用了this變量。對構(gòu)造函數(shù)使用new運算符,就能生成實例,并且this變量會綁定在實例對象上。
每一個構(gòu)造函數(shù)都有一個prototype屬性,指向另一個對象。這個對象的所有屬性和方法,都會被構(gòu)造函數(shù)的實例繼承。
這意味著,我們可以把那些不變的屬性和方法,直接定義在prototype對象上。
//構(gòu)造函數(shù)模式 function Person(age, name){ //Class this.age = age; this.name = name; } //將公共的屬性或方法放在prototype屬性上 Person.prototype.headCount = 1; //創(chuàng)建實例對象 var p = new Person(19, "johnsom"); var p1 = new Person(20, "allen");this
this表示當(dāng)前對象,如果在全局作用范圍內(nèi)使用this,則指代當(dāng)前頁面對象window; 如果在函數(shù)中使用this,則this指代什么是根據(jù)運行時此函數(shù)在什么對象上被調(diào)用。 我們還可以使用apply和call兩個全局方法來改變函數(shù)中this的具體指向。
1. 全局代碼中的thisconsole.log(this === window); //true 全局范圍內(nèi)使用this指向window對象2. 普通的函數(shù)調(diào)用
function f(){ this.name = "tony"; // this在運行時指向window對象,在嚴格模式下則是undefined }3. 在對象中使用
var o = { name: "tony", print: function(){ console.log(this.name); //this指向?qū)ο髈,但是可以改變其指向 } };4. 作為構(gòu)造函數(shù)
new F(); // 函數(shù)內(nèi)部的this指向新創(chuàng)建的對象。5. 多層嵌套的內(nèi)部函數(shù)
var name = "global"; var person = { name : "person", hello : function(sth){ var sayhello = function(sth) { console.log(this.name + " says " + sth); }; sayhello(sth); } } person.hello("hello world");//global says hello world
在內(nèi)部函數(shù)中,this沒有按預(yù)想的綁定到外層函數(shù)對象上,而是綁定到了全局對象。這里普遍被認為是JavaScript語言的設(shè)計錯誤,因為沒有人想讓內(nèi)部函數(shù)中的this指向全局對象。一般的處理方式是將this作為變量保存下來,一般約定為that或者self:
var name = "global"; var person = { name : "person", hello : function(sth){ var that = this; var sayhello = function(sth) { console.log(that.name + " says " + sth); }; sayhello(sth); } } person.hello("hello world");//person says hello world6. 事件中的this
var ele = document.getElementById("id"); ele.addEventListener("click",function(){ console.log(this); //this指向dom元素 });7. 使用apply和call改變this的指向
apply和call類似,只是后面的參數(shù)是通過一個數(shù)組傳入,而不是分開傳入。兩者都是將某個函數(shù)綁定到某個具體對象上使用,自然此時的this會被顯式的設(shè)置為第一個參數(shù)。兩者的方法定義:
call( thisArg [,arg1,arg2,… ] ); // 參數(shù)列表,arg1,arg2,... apply(thisArg [,argArray] ); // 參數(shù)數(shù)組,argArray
var name = "global"; var o = { name: "job", getName: function(){ console.log(this.name); } }; o.getName(); // job //用call或apply改變函數(shù)中this的指向 o.getName.call(this); // global
簡單的總結(jié):
當(dāng)函數(shù)作為對象的方法調(diào)用時,this指向該對象。
當(dāng)函數(shù)作為淡出函數(shù)調(diào)用時,this指向全局對象(嚴格模式時,為undefined)
構(gòu)造函數(shù)中的this指向新創(chuàng)建的對象
嵌套函數(shù)中的this不會繼承上層函數(shù)的this,如果需要,可以用一個變量保存上層函數(shù)的this。
8. bind()一個問題:
$("#ele").click = obj.handler;
如果在handler中用了this,this會綁定在obj上么?顯然不是,賦值以后,函數(shù)是在回調(diào)中執(zhí)行的,this會綁定到$(“#some-div”)元素上。那我們?nèi)绾文芙鉀Q回調(diào)函數(shù)綁定的問題?ES5中引入了一個新的方法,bind():
fun.bind(thisArg[, arg1[, arg2[, ...]]]) thisArg 當(dāng)綁定函數(shù)被調(diào)用時,該參數(shù)會作為原函數(shù)運行時的this指向.當(dāng)使用new 操作符調(diào)用綁定函數(shù)時,該參數(shù)無效. arg1, arg2, ... 當(dāng)綁定函數(shù)被調(diào)用時,這些參數(shù)加上綁定函數(shù)本身的參數(shù)會按照順序作為原函數(shù)運行時的參數(shù).
該方法創(chuàng)建一個新函數(shù),稱為綁定函數(shù),綁定函數(shù)會以創(chuàng)建它時傳入bind方法的第一個參數(shù)作為this,傳入bind方法的第二個以及以后的參數(shù)加上綁定函數(shù)運行時本身的參數(shù)按照順序作為原函數(shù)的參數(shù)來調(diào)用原函數(shù).
$("#ele").click(person.hello.bind(person)); //相應(yīng)元素被點擊時,輸出person says hello world
該方法也很容易模擬,看下Prototype.js中bind方法的源碼:
Function.prototype.bind = function(){ var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift(); return function(){ return fn.apply(object, args.concat(Array.prototype.slice.call(arguments))); }; };參考資料
js老生常談之this,constructor ,prototype
詳解JavaScript中的this
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/91625.html
摘要:在構(gòu)造函數(shù)中的中定義的屬性和方法,會被創(chuàng)建的對象所繼承下來。從上面的輸出結(jié)果看出,指向了其構(gòu)造函數(shù)的,而本身也是一個對象,其內(nèi)部也有屬性,其指向的是直到最后指向,這條原型鏈才結(jié)束。和都指向,說明原型鏈到終止。 prototype原型對象 每個函數(shù)都有一個默認的prototype屬性,其實際上還是一個對象,如果被用在繼承中,姑且叫做原型對象。 在構(gòu)造函數(shù)中的prototype中定義的屬性...
摘要:了解面向?qū)ο缶幊讨?,首先要了解的?zhí)行順序。的解析過程分為兩個階段預(yù)處理階段與執(zhí)行期。在執(zhí)行階段的執(zhí)行上下文對象由賦值為指向?qū)?yīng)函數(shù) 了解js面向?qū)ο缶幊讨?,首先要了解js的執(zhí)行順序。js的解析過程分為兩個階段:預(yù)處理階段與執(zhí)行期。 預(yù)處理階段 在預(yù)處理階段,js會首先創(chuàng)建一個執(zhí)行上下文對象(Execute Context,然后掃描聲明式函數(shù)和用var定義的變量,將其加入執(zhí)行上下文環(huán)...
摘要:的變量作用域是基于其特有的作用域鏈的。需要注意的是,用創(chuàng)建的函數(shù),其作用域指向全局作用域。所以,有另一種說法認為閉包是由函數(shù)和與其相關(guān)的引用環(huán)境組合而成的實體。 作用域 定義 在編程語言中,作用域控制著變量與參數(shù)的可見性及生命周期,它能減少名稱沖突,而且提供了自動內(nèi)存管理 --javascript 語言精粹 我理解的是,一個變量、函數(shù)或者成員可以在代碼中訪問到的范圍。 js的變量作...
摘要:構(gòu)造函數(shù)通常首字母大寫,用于區(qū)分普通函數(shù)。這種關(guān)系常被稱為原型鏈,它解釋了為何一個對象會擁有定義在其他對象中的屬性和方法。中所有的對象,都有一個屬性,指向?qū)嵗龑ο蟮臉?gòu)造函數(shù)原型由于是個非標(biāo)準(zhǔn)屬性,因此只有和兩個瀏覽器支持,標(biāo)準(zhǔn)方法是。 從這篇文章開始,復(fù)習(xí) MDN 中級教程 的內(nèi)容了,在初級教程中,我和大家分享了一些比較簡單基礎(chǔ)的知識點,并放在我的 【Cute-JavaScript】系...
摘要:類的繼承建立繼承關(guān)系修改的指向調(diào)用父類方法調(diào)用父類的構(gòu)造器調(diào)用父類上的方法封裝命名空間是沒有命名空間的,因此可以用對象模擬。參考資料面向?qū)ο? 面向?qū)ο蟪绦蛟O(shè)計(Object-oriented programming,OOP)是一種程序設(shè)計范型,同時也是一種程序開發(fā)的方法。對象指的是類的實例。它將對象作為程序的基本單元,將程序和數(shù)據(jù)封裝其中,以提高軟件的重用性、靈活性和擴展性?!S基百...
閱讀 2022·2021-09-30 09:46
閱讀 1428·2019-08-30 15:43
閱讀 1201·2019-08-29 13:28
閱讀 1985·2019-08-29 11:24
閱讀 1776·2019-08-26 13:22
閱讀 4097·2019-08-26 12:01
閱讀 1881·2019-08-26 11:33
閱讀 3293·2019-08-23 15:34