成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

對(duì)JavaScript對(duì)象的理解

aboutU / 613人閱讀

摘要:面向?qū)ο缶幊陶Z(yǔ)言的對(duì)象體系,不是基于類(lèi)的,而是基于構(gòu)造函數(shù)和原型鏈。一語(yǔ)言使用構(gòu)造函數(shù)作為對(duì)象的模板。構(gòu)造函數(shù)之所以叫構(gòu)造函數(shù),就是說(shuō)這個(gè)函數(shù)的目的,就是操作一個(gè)空對(duì)象即對(duì)象,將其構(gòu)造為需要的樣子。

Javascript
前言:關(guān)于javascript我總有些疑問(wèn),是不是一門(mén)面向?qū)ο蟮恼Z(yǔ)言,總結(jié)了很久:Javascript是一種基于對(duì)象(object-based)的語(yǔ)言,你遇到的所有東西幾乎都是對(duì)象。但是,它又不是一種真正的面向?qū)ο缶幊蹋∣OP)語(yǔ)言,其實(shí)主要是因?yàn)樗鼪](méi)有提供象抽象、繼承、重載等有關(guān)面向?qū)ο笳Z(yǔ)言的許多功能, 而是把其它語(yǔ)言所創(chuàng)建的復(fù)雜對(duì)象統(tǒng)一起來(lái),從而形成一個(gè)非常強(qiáng)大的對(duì)象系統(tǒng)。 這種獨(dú)特性稱(chēng)它為prototype-basedOO(基于原型的面向?qū)ο?。  (這是針對(duì)ES6以前的標(biāo)準(zhǔn)) 

在這篇博客中我引用了阮一峰老師的教程:http://javascript.ruanyifeng.com/oop/basic.html 這個(gè)教程講得十分詳細(xì),如果有系統(tǒng)學(xué)習(xí)的需要,建議跳過(guò)我的文章,直接看這里。

js面向?qū)ο缶幊?/b>

JavaScript 語(yǔ)言的對(duì)象體系,不是基于“類(lèi)”的,而是基于構(gòu)造函數(shù)(constructor)和原型鏈(prototype)。

一、JavaScript 語(yǔ)言使用構(gòu)造函數(shù)(constructor)作為對(duì)象的模板。

var User = function () {

this.age = 23;
this.name = "wanghaoxin";

};

這是一個(gè)構(gòu)造函數(shù)。

構(gòu)造函數(shù)的寫(xiě)法就是一個(gè)普通的函數(shù),但是有自己的特征和用法。

函數(shù)體內(nèi)部使用了this關(guān)鍵字,代表了所要生成的對(duì)象實(shí)例。

生成對(duì)象的時(shí)候,必需用new命令,調(diào)用Vehicle函數(shù)。

var user = new User();//這里的等同于 var user = new User;
user.age = 123;
console.log(user.age);
console.log(user.name);

執(zhí)行這段代碼結(jié)果就是 123 、 wanghaoxin,這里的user.age經(jīng)過(guò)了賦值,所以是賦值后的值。

由于js并不是java一樣的強(qiáng)類(lèi)型語(yǔ)言,所以不能再編譯前檢查你的語(yǔ)法錯(cuò)誤,這里有個(gè)問(wèn)題。

> 一個(gè)很自然的問(wèn)題是,如果忘了使用new命令,直接調(diào)用構(gòu)造函數(shù)會(huì)發(fā)生什么事?

這種情況下,構(gòu)造函數(shù)就變成了普通函數(shù),并不會(huì)生成實(shí)例對(duì)象。而且由于后面會(huì)說(shuō)到的原因,this這時(shí)代表全局對(duì)象,將造成一些意想不到的結(jié)果。

二、new命令的原理

使用new命令時(shí),它后面的函數(shù)調(diào)用就不是正常的調(diào)用,而是依次執(zhí)行下面的步驟。

    1. 創(chuàng)建一個(gè)空對(duì)象,作為將要返回的對(duì)象實(shí)例. 
    2. 將這個(gè)空對(duì)象的原型,指向構(gòu)造函數(shù)的prototype屬性.
    3. 將這個(gè)空對(duì)象賦值給函數(shù)內(nèi)部的this關(guān)鍵字.
    4. 開(kāi)始執(zhí)行構(gòu)造函數(shù)內(nèi)部的代碼.

也就是說(shuō),構(gòu)造函數(shù)內(nèi)部,this指的是一個(gè)新生成的空對(duì)象,所有針對(duì)this的操作,都會(huì)發(fā)生在這個(gè)空對(duì)象上。構(gòu)造函數(shù)之所以叫“構(gòu)造函數(shù)”,就是說(shuō)這個(gè)函數(shù)的目的,就是操作一個(gè)空對(duì)象(即this對(duì)象),將其“構(gòu)造”為需要的樣子。

如果構(gòu)造函數(shù)內(nèi)部有return語(yǔ)句,而且return后面跟著一個(gè)對(duì)象,new命令會(huì)返回return語(yǔ)句指定的對(duì)象;否則,就會(huì)不管return語(yǔ)句,返回this對(duì)象。

三、使用 Object.create() 創(chuàng)建實(shí)例對(duì)象

構(gòu)造函數(shù)作為模板,可以生成實(shí)例對(duì)象。但是,有時(shí)只能拿到實(shí)例對(duì)象,而該對(duì)象根本就不是由構(gòu)造函數(shù)生成的,這時(shí)可以使用Object.create()方法,直接以某個(gè)實(shí)例對(duì)象作為模板,生成一個(gè)新的實(shí)例對(duì)象。

    var person1 = {
      name: "張三",
      age: 38,
      greeting: function() {
        console.log("Hi! I"m " + this.name + ".");
      }
    };
    
    var person2 = Object.create(person1);
    
    person2.name // 張三
    person2.greeting() // Hi! I"m 張三.

四、javascript使用prototype

JavaScript 的每個(gè)對(duì)象都繼承另一個(gè)對(duì)象,后者稱(chēng)為“原型”(prototype)對(duì)象。null也可以充當(dāng)原型,區(qū)別在于它沒(méi)有自己的原型對(duì)象。JavaScript 繼承機(jī)制的設(shè)計(jì)就是,原型的所有屬性和方法,都能被子對(duì)象共享。

function Animal(name) {
  this.name = name;
}

Animal.prototype.color = "white";

var cat1 = new Animal("大毛");
var cat2 = new Animal("二毛");

cat1.color // "white"
cat2.color // "white"

這里的color屬性被兩個(gè)貓共享了。

cat1.color = "black";

cat1.color // "black"
cat2.color // "yellow"
Animal.prototype.color // "yellow";

在這里cat1.color 被賦值為 black ,所以cat1將不再使用原來(lái)的原型屬性.

prototype對(duì)象有一個(gè)constructor屬性,默認(rèn)指向prototype對(duì)象所在的構(gòu)造函數(shù)。由于constructor屬性定義在prototype對(duì)象上面,意味著可以被所有實(shí)例對(duì)象繼承。

構(gòu)造函數(shù)就是普通的函數(shù), 所以實(shí)際上所有函數(shù)都有prototype屬性。

五、_proto_原型鏈

對(duì)象的屬性和方法,有可能定義在自身,也有可能定義在它的原型對(duì)象。由于原型本身也是對(duì)象,又有自己的原型,所以形成了一條原型鏈(prototype chain)。比如,a對(duì)象是b對(duì)象的原型,b對(duì)象是c對(duì)象的原型,以此類(lèi)推。

如果一層層地上溯,所有對(duì)象的原型最終都可以上溯到Object.prototype,即Object構(gòu)造函數(shù)的prototype屬性。那么,Object.prototype對(duì)象有沒(méi)有它的原型呢?回答是有的,就是沒(méi)有任何屬性和方法的null對(duì)象,而null對(duì)象沒(méi)有自己的原型。

“原型鏈”的作用是,讀取對(duì)象的某個(gè)屬性時(shí),JavaScript 引擎先尋找對(duì)象本身的屬性,如果找不到,就到它的原型去找,如果還是找不到,就到原型的原型去找。如果直到最頂層的Object.prototype還是找不到,則返回undefined。

如果對(duì)象自身和它的原型,都定義了一個(gè)同名屬性,那么優(yōu)先讀取對(duì)象自身的屬性,這叫做“覆蓋”(overriding)。

Object.prototype.__proto__

根據(jù)語(yǔ)言標(biāo)準(zhǔn),__proto__屬性只有瀏覽器才需要部署,其他環(huán)境可以沒(méi)有這個(gè)屬性,而且前后的兩根下劃線,表示它本質(zhì)是一個(gè)內(nèi)部屬性,不應(yīng)該對(duì)使用者暴露。因此,應(yīng)該盡量少用這個(gè)屬性,而是用Object.getPrototypeof()(讀?。┖蚈bject.setPrototypeOf()(設(shè)置),進(jìn)行原型對(duì)象的讀寫(xiě)操作。

this及this的綁定

this的動(dòng)態(tài)切換,固然為JavaScript創(chuàng)造了巨大的靈活性,但也使得編程變得困難和模糊。有時(shí),需要把this固定下來(lái),避免出現(xiàn)意想不到的情況。JavaScript提供了call、apply、bind這三個(gè)方法,來(lái)切換/固定this的指向。

this的使用

這個(gè)關(guān)鍵字很好的體現(xiàn)了,如果不是面向?qū)ο?,那為什么使用this呢,其實(shí)這個(gè)this還真有點(diǎn)不一樣,在java中this就是指的本類(lèi),那么js中呢?

this永遠(yuǎn)指向的是最后調(diào)用它的對(duì)象,也就是看它執(zhí)行的時(shí)候是誰(shuí)調(diào)用的。

所以這里需要注意的問(wèn)題就是,到底是哪個(gè)對(duì)象最后調(diào)用了this,只有因?yàn)閠his本身指代的就是對(duì)象。下面的例子中this的指向變了,變成了誰(shuí)(誰(shuí)調(diào)用了), 一目了然。

function f() {
  return "姓名:"+ this.name;
}

var A = {
  name: "張三",
  describe: f
};

var B = {
  name: "李四",
  describe: f
};

A.describe() // "姓名:張三"
B.describe() // "姓名:李四"

如果沒(méi)有對(duì)象調(diào)用他,默認(rèn)是用window對(duì)象調(diào)用的,這也講得通,因?yàn)閣indow是js的頂層對(duì)象,所有其他對(duì)象都是window的下屬對(duì)象,JavaScript規(guī)定,瀏覽器環(huán)境的所有全局變量,都是window對(duì)象的屬性。如果一個(gè)函數(shù)在全局環(huán)境中運(yùn)行,那么this就是指頂層對(duì)象。

具體的例子看下面鏈接,比我寫(xiě)的好,
這里有詳細(xì)的講解http://www.cnblogs.com/pssp/p/5216085.html

call的使用

函數(shù)實(shí)例的call方法,可以指定函數(shù)內(nèi)部this的指向(即函數(shù)執(zhí)行時(shí)所在的作用域),然后在所指定的作用域中,調(diào)用該函數(shù)。call方法的參數(shù),應(yīng)該是一個(gè)對(duì)象。如果參數(shù)為空、null和undefined,則默認(rèn)傳入全局對(duì)象。

var obj = {};

var f = function () {
  return this;
};

f() === this // true
f.call(obj) === obj // true

上面代碼中,在全局環(huán)境運(yùn)行函數(shù)f時(shí),this指向全局環(huán)境;call方法可以改變this的指向,指定this指向?qū)ο髈bj,然后在對(duì)象obj的作用域中運(yùn)行函數(shù)f。

var n = 123;
var obj = { n: 456 };

function a() {
  console.log(this.n);
}

a.call() // 123
a.call(null) // 123
a.call(undefined) // 123
a.call(window) // 123
a.call(obj) // 456

上面代碼中,a函數(shù)中的this關(guān)鍵字,如果指向全局對(duì)象,返回結(jié)果為123。如果使用call方法將this關(guān)鍵字指向obj對(duì)象,返回結(jié)果為456??梢钥吹?,如果call方法沒(méi)有參數(shù),或者參數(shù)為null或undefined,則等同于指向全局對(duì)象。

function add(a, b) {
  return a + b;
}

add.call(this, 1, 2) // 3

上面代碼中,call方法指定函數(shù)add內(nèi)部的this綁定當(dāng)前環(huán)境(對(duì)象),并且參數(shù)為1和2,因此函數(shù)add運(yùn)行后得到3。

var obj = {};
obj.hasOwnProperty("toString") // false

// 覆蓋掉繼承的 hasOwnProperty 方法
obj.hasOwnProperty = function () {
  return true;
};
obj.hasOwnProperty("toString") // true

Object.prototype.hasOwnProperty.call(obj, "toString") // false

上面代碼中,hasOwnProperty是obj對(duì)象繼承的方法,如果這個(gè)方法一旦被覆蓋,就不會(huì)得到正確結(jié)果。call方法可以解決這個(gè)問(wèn)題,它將hasOwnProperty方法的原始定義放到obj對(duì)象上執(zhí)行,這樣無(wú)論obj上有沒(méi)有同名方法,都不會(huì)影響結(jié)果。

apply的使用

apply方法的作用與call方法類(lèi)似,也是改變this指向,然后再調(diào)用該函數(shù)。唯一的區(qū)別就是,它接收一個(gè)數(shù)組作為函數(shù)執(zhí)行時(shí)的參數(shù),使用格式如下。

function f(x,y){
  console.log(x+y);
}

f.call(null,1,1) // 2
f.apply(null,[1,1]) // 2

上面的 f 函數(shù)本來(lái)接受兩個(gè)參數(shù),使用apply方法以后,就變成可以接受一個(gè)數(shù)組作為參數(shù)。

綁定回調(diào)函數(shù)的對(duì)象

var o = new Object();
o.f = function () {
console.log(this === o);
}
var f = function (){
o.f.apply(o);
// 或者 o.f.call(o);
};
$("#button").on("click", f);

點(diǎn)擊按鈕以后,控制臺(tái)將會(huì)顯示true。由于apply方法(或者call方法)不僅綁定函數(shù)執(zhí)行時(shí)所在的對(duì)象,還會(huì)立即執(zhí)行函數(shù),因此不得不把綁定語(yǔ)句寫(xiě)在一個(gè)函數(shù)體內(nèi)。更簡(jiǎn)潔的寫(xiě)法是采用下面介紹的bind方法。

bind的使用

bind方法用于將函數(shù)體內(nèi)的this綁定到某個(gè)對(duì)象,然后返回一個(gè)新函數(shù)。

var counter = {
  count: 0,
  inc: function () {
    this.count++;
  }
};

var func = counter.inc;
func();
counter.count // 0
count // NaN

上面代碼中,函數(shù)func是在全局環(huán)境中運(yùn)行的,這時(shí)inc內(nèi)部的this指向頂層對(duì)象window,所以counter.count是不會(huì)變的,反而創(chuàng)建了一個(gè)全局變量count。因?yàn)閣indow.count原來(lái)等于undefined,進(jìn)行遞增運(yùn)算后undefined++就等于NaN。

為了解決這個(gè)問(wèn)題,可以使用bind方法,將inc內(nèi)部的this綁定到counter對(duì)象。

var func = counter.inc.bind(counter);
func();
counter.count // 1

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/107338.html

相關(guān)文章

  • 面向對(duì) JavaScript

    摘要:是完全的面向?qū)ο笳Z(yǔ)言,它們通過(guò)類(lèi)的形式組織函數(shù)和變量,使之不能脫離對(duì)象存在。而在基于原型的面向?qū)ο蠓绞街校瑢?duì)象則是依靠構(gòu)造器利用原型構(gòu)造出來(lái)的。 JavaScript 函數(shù)式腳本語(yǔ)言特性以及其看似隨意的編寫(xiě)風(fēng)格,導(dǎo)致長(zhǎng)期以來(lái)人們對(duì)這一門(mén)語(yǔ)言的誤解,即認(rèn)為 JavaScript 不是一門(mén)面向?qū)ο蟮恼Z(yǔ)言,或者只是部分具備一些面向?qū)ο蟮奶卣?。本文將回歸面向?qū)ο蟊疽?,從?duì)語(yǔ)言感悟的角度闡述為什...

    novo 評(píng)論0 收藏0
  • 加深對(duì) JavaScript This 理解

    摘要:使用來(lái)調(diào)用函數(shù),會(huì)自動(dòng)執(zhí)行下面操作創(chuàng)建一個(gè)全新的對(duì)象。所以如果是一個(gè)函數(shù)的話,會(huì)是這樣子的創(chuàng)建一個(gè)新對(duì)象連接新對(duì)象與函數(shù)的原型執(zhí)行函數(shù),改變指向新的對(duì)象所以,在使用來(lái)調(diào)用函數(shù)時(shí)候,我們會(huì)構(gòu)造一個(gè)新對(duì)象并把它綁定到函數(shù)調(diào)用中的上。 歡迎來(lái)我的博客閱讀:《加深對(duì) JavaScript This 的理解》 我相信你已經(jīng)看過(guò)很多關(guān)于 JavaScript 的 this 的談?wù)摿?,既然你點(diǎn)進(jìn)來(lái)...

    PiscesYE 評(píng)論0 收藏0
  • 理解JavaScript核心知識(shí)點(diǎn):原型

    摘要:首先,需要來(lái)理清一些基礎(chǔ)的計(jì)算機(jī)編程概念編程哲學(xué)與設(shè)計(jì)模式計(jì)算機(jī)編程理念源自于對(duì)現(xiàn)實(shí)抽象的哲學(xué)思考,面向?qū)ο缶幊淌瞧湟环N思維方式,與它并駕齊驅(qū)的是另外兩種思路過(guò)程式和函數(shù)式編程。 JavaScript 中的原型機(jī)制一直以來(lái)都被眾多開(kāi)發(fā)者(包括本人)低估甚至忽視了,這是因?yàn)榻^大多數(shù)人沒(méi)有想要深刻理解這個(gè)機(jī)制的內(nèi)涵,以及越來(lái)越多的開(kāi)發(fā)者缺乏計(jì)算機(jī)編程相關(guān)的基礎(chǔ)知識(shí)。對(duì)于這樣的開(kāi)發(fā)者來(lái)說(shuō) J...

    iKcamp 評(píng)論0 收藏0
  • Javascript】深入理解this作用域問(wèn)題以及new/let/var/const對(duì)this作

    摘要:理解作用域高級(jí)程序設(shè)計(jì)中有說(shuō)到對(duì)象是在運(yùn)行時(shí)基于函數(shù)的執(zhí)行環(huán)境綁定的在全局函數(shù)中,等于,而當(dāng)函數(shù)被作為某個(gè)對(duì)象調(diào)用時(shí),等于那個(gè)對(duì)象。指向與匿名函數(shù)沒(méi)有關(guān)系如果函數(shù)獨(dú)立調(diào)用,那么該函數(shù)內(nèi)部的,則指向。 理解this作用域 《javascript高級(jí)程序設(shè)計(jì)》中有說(shuō)到: this對(duì)象是在運(yùn)行時(shí)基于函數(shù)的執(zhí)行環(huán)境綁定的:在全局函數(shù)中,this等于window,而當(dāng)函數(shù)被作為某個(gè)對(duì)象調(diào)用時(shí),t...

    snowLu 評(píng)論0 收藏0
  • 深入理解JavaScript系列11:根本沒(méi)有“JSON對(duì)象”這回事

    摘要:更多資料如果你想了解更多關(guān)于的資料,下面的連接對(duì)你絕對(duì)有用關(guān)于本文本文轉(zhuǎn)自大叔的深入理解系列。深入理解系列文章,包括了原創(chuàng),翻譯,轉(zhuǎn)載,整理等各類(lèi)型文章,原文是大叔的一個(gè)非常不錯(cuò)的專(zhuān)題,現(xiàn)將其重新整理發(fā)布。 前言 寫(xiě)這篇文章的目的是經(jīng)??吹介_(kāi)發(fā)人員說(shuō):把字符串轉(zhuǎn)化為JSON對(duì)象,把JSON對(duì)象轉(zhuǎn)化成字符串等類(lèi)似的話題,所以把之前收藏的一篇老外的文章整理翻譯了一下,供大家討論,如有錯(cuò)誤,...

    darryrzhong 評(píng)論0 收藏0
  • JavaScript閉包

    摘要:閉包引起的內(nèi)存泄漏總結(jié)從理論的角度將由于作用域鏈的特性中所有函數(shù)都是閉包但是從應(yīng)用的角度來(lái)說(shuō)只有當(dāng)函數(shù)以返回值返回或者當(dāng)函數(shù)以參數(shù)形式使用或者當(dāng)函數(shù)中自由變量在函數(shù)外被引用時(shí)才能成為明確意義上的閉包。 文章同步到github js的閉包概念幾乎是任何面試官都會(huì)問(wèn)的問(wèn)題,最近把閉包這塊的概念梳理了一下,記錄成以下文章。 什么是閉包 我先列出一些官方及經(jīng)典書(shū)籍等書(shū)中給出的概念,這些概念雖然...

    HmyBmny 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<