თუ თქვენ ხედავთ ამ შეტყობინებას, ესე იგი საიტზე გარე რესურსების ჩატვირთვისას მოხდა შეფერხება.

If you're behind a web filter, please make sure that the domains *.kastatic.org and *.kasandbox.org are unblocked.

ძირითადი მასალა

ღილაკის ტიპის ობიექტი

კოდის ხელახლა გამოყენებადად გადაქცევისა და გაძლიერების ერთ-ერთი საშუალებაა ობიექტზე ორიენტირებული პროგრამირება, განსაკუთრებით UI კონტროლების გაკეთებისას, როგორიცაა ღილაკები. ობიექტზე ორიენტირებულ პროგრამირებაში ჩვენი პროგრამის სამყაროს აღვიქვამთ აბსტრაქტული ობიექტების ტიპებად, რომელთაც აქვთ კონკრეტული ქცევა და შემდეგ ვქმნით ამ ობიექტების ტიპების ნიმუშებს კონკრეტული პარამეტრებით. თუ არ გახსოვთ, როგორ კეთდება ეს JavaScript-ში, მიმოიხილეთ აქ.
ღილაკების შესაქმნელად OOP-ს (ობიექტზე ორიენტირებული პროგრამირების) გამოსაყენებლად დაგვჭირდება Button ობიექტის ტიპის განსაზღვრა და შემდეგ მასში მეთოდების განსაზღვრა, როგორიცაა მისი დახატვა და მაუსის დაწკაპუნებებზე რეაგირება. კარგი იქნება, თუ შევძლებთ ისეთი კოდის დაწერაც, რომელიც ასე გამოიყურება:
var btn1 = new Button(...);
btn1.draw();

mouseClicked = function() {
  if (btn1.isMouseInside()) {
     println("ვა, თქვენ მე დამაწკაპეთ!");
  }
}
მოდით, შევადაროთ ის კოდს, რომელიც წინა პარაგრაფში დავწერეთ:
var btn1 = {...};
drawButton(btn1);

mouseClicked = function() {
  if (isMouseInside(btn1)) {
     println("ვა, თქვენ დამაწკაპეთ!");
  }
}
ერთმანეთს ძალიან ჰგვანან, არა? მაგრამ დიდი განსხვავებაა -- ყველა ფუნქცია განსაზღვრული Button ობიექტის ტიპზე, ისინი ეკუთვნიან ღილაკებს. უფრო მჭიდრო დაწყვილებაა თვისებებსა და ქცევას შორის და ამის შედეგად ვიღებთ უფრო სუფთა და ხელახლა გამოყენებად კოდს.
Button ობიექტის ტიპის განსაზღვრისთვის უნდა დავიწყოთ კონსტრუქტორით: სპეციალური ფუნქცია, რომელიც იღებს კონფიგურაციის პარამეტრებს და ობიექტის ნიმუშის საწყის თვისებებს ანიჭებს მნიშვნელობებს.
პირველი მცდელობისთვის, აი, კონსტრუქტორი, რომელიც იღებს x-ს, y-ს, სიგანესა და სიმაღლეს:
var Button = function(x, y, width, height) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
};

var btn1 = new Button(100, 100, 150, 150);
ეს ნამდვილად მუშაობს, მაგრამ მე სხვა მიდგომა მაქვს, რომელსაც რეკომენდაციას ვუწევ. ცალკეული პარამეტრების მიღების ნაცვლად კონსტრუქტორმა მიიღოს კონფიგურაციის ობიექტი.
var Button = function(config) {
    this.x = config.x;
    this.y = config.y;
    this.width = config.width;
    this.height = config.height;
    this.label = config.label;
};
config ობიექტის უპირატესობა არის ის, რომ შეგვიძლია, გავაგრძელოთ პარამეტრების დამატება, რომელსაც კონსტრუქტორი მიხედავს (მაგალითად, label) და ჩვენთვის კვლავ ადვილად გასაგები არის, რას აკეთებს თითოეული პარამეტრი, როდესაც ღილაკს ვქმნით:
var btn1 = new Button({
    x: 100, y: 100,
    width: 150, height: 50,
    label: "დააწკაპეთ გეთაყვა!"});
მაგრამ ჩვენ შეგვიძლია, ამაზე ერთი ნაბიჯით წინ წავიდეთ. რა აზრის ხართ, ყველა ღილაკს რომ ერთი და იგივე სიგრძე და სიგანე ჰქონდეს? ჩვენ არ უნდა დაგვჭირდეს სიგრძისა და სიგანის პარამეტრების ყოველ ჯერზე მითითება, მხოლოდ მაშინ უნდა მივუთითოთ, როცა საჭიროა. ჩვენ შეგვიძლია, კონსტრუქტორს შევამოწმებინოთ, თვისება განსაზღვრულია თუ არა config ობიექტში და უარყოფითი პასუხის შემთხვევაში მივუთითოთ საწყისი მნიშვნელობა. ეს შემდეგნაირად კეთდება:
var Button = function(config) {
    this.x = config.x || 0;
    this.y = config.y || 0;
    this.width = config.width || 150;
    this.height = config.height || 50;
    this.label = config.label || "დაწკაპება";
};
ახლა უკვე მისი გამოძახება მხოლოდ რამდენიმე თვისებით შეგვიძლია, რადგან დანარჩენებს საწყისი მნიშვნელობები მიენიჭებათ:
var btn1 = new Button({x: 100, y: 100, label: "Please click!"});
ამდენი მუშაობა კონსტრუქტორისთვის? მაგრამ ეს ყველაფერი ამად ღირს, გეფიცებით.
ახლა, როცა კონსტრუქტორზე მუშაობას მოვრჩით, ქცევაც განვსაზღვროთ: draw მეთოდი. ეს იქნება იგივე კოდი, რაც drawButton ფუნქცია, მაგრამ ის ყველა თვისებას აიღებს this-იდან, რადგან ის განსაზღვრულია თვითონ ობიექტის პროტოტიპზე:
Button.prototype.draw = function() {
    fill(0, 234, 255);
    rect(this.x, this.y, this.width, this.height, 5);
    fill(0, 0, 0);
    textSize(19);
    textAlign(LEFT, TOP);
    text(this.label, this.x+10, this.y+this.height/4);
};
როგორც კი ის განისაზღვრება, შეგიძლია, ასე გამოვიძახოთ:
btn1.draw();
აი, პროგრამა, რომელიც იყენებს ამ Button ობიექტს 2 ღილაკის შესაქმნელად - ნახეთ, რამდენად იოლია ბევრი ღილაკის შექმნა და დახატვა:
ჩვენ გამოვტოვეთ რთული ნაწილი: დაწკაპუნებებზე გამკლავება. შეგვიძლია, დავიწყოთ Button-ის პროტოტიპზე ფუნქციის განსაზღვრით, რომელიც დააბრუნებს true-ს, თუ მომხმარებელმა დააწკაპუნა კონკრეტული ღილაკის შემომსაზღვრელ ყუთზე. კიდევ ერთხელ, ეს ზუსტად იგივეა, რაც ჩვენი წინა ფუნქცია, მაგრამ ის ყველა თვისებას მასში გადაცემული ობიექტის ნაცვლად იღებს this-იდან.
Button.prototype.isMouseInside = function() {
    return mouseX > this.x &&
           mouseX < (this.x + this.width) &&
           mouseY > this.y &&
           mouseY < (this.y + this.height);
};
ახლა მისი გამოყენება შეგვიძლია mouseClicked ფუნქციიდან:
mouseClicked = function() {
    if (btn1.isMouseInside()) {
        println("თქვენ სწორი გადაწყვეტილება მიიღეთ!");
    } else if (btn2.isMouseInside()) {
        println("რა კარგია, თქვენ მე ამირჩიეთ!");
    }
};
სცადეთ ის ქვემოთ, თითოეულ ღილაკზე დაწკაპუნებით:
მაგრამ არ მომწონს, როგორც ვრეაგირებთ დაწკაპუნებაზე. ობიექტზე ორიენტირებული პროგრამირების მთელი იდეა არის ობიექტთან დაკავშირებული ყველა ქცევის ამ ობიექტში თავმოყრა და ქცევის სამართავად თვისებების გამოყენება, მაგრამ ჩვენ ქცევის ნაწილი დავტოვეთ ობიექტს მიღმა, println-ები mouseClicked-ის შიგნით:
mouseClicked = function() {
    if (btn1.isMouseInside()) {
        println("თქვენ სწორი გადაწყვეტილება მიიღეთ!");
    } else if (btn2.isMouseInside()) {
        println("რა კარგია, თქვენ მე ამირჩიეთ!");
    }
};
დაბეჭდვის ეს დებულებები რამენაირად უნდა იყოს მიმაგრებული თითოეულ ღილაკზე, თითქოს კონსტრუქტორს გადავცემდეთ რამეს. მისი ახლანდელი მდგომარეობის მიხედვით, შეგვიძლია, მესიჯი გადავცეთ კონსტრუქტორის კონფიგურაციას და განვსაზღვროთ handleMouseClick ფუნქცია მის დასაბეჭდად:
var Button = function(config) {
    ...
    this.message = config.message || "დაწკაპებულია!";
};

Button.prototype.handleMouseClick = function() {
    if (this.isMouseInside()) {
         println(this.message);
    }
};

var btn1 = new Button({
    x: 100,
    y: 100,
    label: "დააწკაპეთ, გეთაყვა!",
    message: "თქვენ სწორი არჩევანი გააკეთეთ!"
});

mouseClicked = function() {
   btn1.handleMouseClick();
};
ეს გაცილებით უკეთესია, რადგან ყველაფერი, რაც დაკავშირებულია თითოეული ღილაკის ქცევასთან, თავმოყრილია კონსტრუქტორში, მაგრამ ეს აგრეთვე ძალიან მარტივია. რა ხდება იმ შემთხვევაში, როცა გვინდა შეტყობინების დაბეჭდვის გარდა სხვა რამის გაკეთებაც, მაგალითად ფიგურების დახატვა ან სცენების შეცვლა, რაიმე, რასაც რამდენიმე ხაზის მქონე კოდი დასჭირდება? ამ შემთხვევაში კონსტრუქტორი უნდა მოვამარაგოთ სტრინგზე მეტი რამით-- ის უნდა მოვამარაგოთ კოდით. როგორ უნდა გადავცეთ კოდი?
...ფუნქციით! JavaScript-ში (მაგრამ არა ყველა ენაში) შეგვიძლია ფუნქციების ფუნქციებისთვის პარამეტრებად გადაცემა. ეს ხელსაყრელია ბევრ სიტუაციაში, მაგრამ განსაკუთრებით ხელსაყრელია ქცევის განსაზღვრისას UI კონტროლებისთვის, როგორიცაა ღილაკები. შეგვიძლია, ღილაკს ვუთხრათ, „აი, ფუნქცია. ეს არის კოდი, რომელიც მინდა, რომ გამოიძახო, როდესაც მომხმარებელი დააჭერს ღილაკს." ამ ფუნქციებს ვეძახით "უკუგამოძახების" ფუნქციებს, რადგან ისინი არ არიან გამოძახებული დაუყოვნებლივ, ისინი იქნებიან გამოძახებული საჭირო დროს.
შეგვიძლია, დავიწყოთ onClick პარამეტრის გადაცემით, რომელიც ფუნქციაა:
var btn1 = new Button({
    x: 100,
    y: 100,
    label: "დააწკაპეთ, გეთაყვა!",
    onClick: function() {
       text("თქვენ სწორი არჩევანი გააკეთეთ!", 100, 300);
    }
});
უნდა დავრწმუდეთ, რომ ჩვენი კონსტრუქტორი onClick თვისებას მნიშვნელობას ანიჭებს იმის მიხედვით, რაც გადაეცა. საწყისი შემთხვევისთვის (თუ onClick არ გადაცემულა) შევქმნით „no-op" ფუნქციას -- ფუნქცია, რომელიც არც ერთ ოპერაციას არ აკეთებს. ის იმისთვის არსებობს, რომ გამოვიძახოთ და არ მივიღოთ შეცდომა.
var Button = function(config) {
    // ...
    this.onClick = config.onClick || function() {};
};
საბოლოოდ, ჩვენ უნდა გამოვიძახოთ უკუგამოძახების ფუნქცია, როგორც კი მომხმარებელი დააწკაპუნებს ღილაკზე. ეს საკმაოდ მარტივია- შეგვიძლია, ის გამოვიძახოთ იმ თვისების სახელის დაწერით, რომელშიც ის დავიმახსოვრეთ და მოვაყოლოთ ცარიელი ფრჩხილები:
Button.prototype.handleMouseClick = function() {
    if (this.isMouseInside()) {
        this.onClick();
    }
};
და ამით მოვრჩით - გვაქვს Button ობიექტი, რომლისგანაც შეგვიძლია, ადვილად შევქმნათ ახალი ღილაკები, თითოეული ღილაკი გავხადოთ განსხვავებული ვიზუალის მქონე და ყოველი მათგანი განსხვავებულ რეაგირებას მოახდენს დაწკაპუნების მოვლენებზე. დააწკაპუნეთ ქვემოთ მოცემულ მაგალითზე და ნახეთ, რა მოხდება:
ახლა, როცა გაქვთ ეს შაბლონი, შეგიძლიათ, თქვენი საკუთარი განსხვავებული ღილაკები გააკეთოთ (მაგალითად, გააკეთოთ ღილაკები, რომლებსაც აქვთ განსხვავებული ფერები, ან სხვა მოვლენებზე რეაგირებენ, როგორიცაა mouseover (მაუსის გადატარება)). სცადეთ ეს თქვენს პროგრამებში!

გსურთ, შეუერთდეთ დისკუსიას?

პოსტები ჯერ არ არის.
გესმით ინგლისური? დააწკაპუნეთ აქ და გაეცანით განხილვას ხანის აკადემიის ინგლისურენოვან გვერდზე.