Отличие Javascript от PHP o_0

    Доброго времени суток уважаемый %username%
    Вот появился на хабре такой замечательный топик Отличие Javascript от PHP ;) не читал, но осуждаю Не знаю чем там всё закончилось все комментарии не смог перечитать, но хотелось бы развеять пару заблуждений и неточностей которые были допущены автором

    итак начнём
    «По умолчанию, всё передается по значению, и объекты тоже
    В PHP попытались возвести в абсолют концепцию языка С, что всё передается по значению. И они поначалу сделали это даже для объектов, но потом немного поменяли концепцию — объекты по-прежнему являются значениями, но это значение представляет из себя ссылку на инстанс класса.» — ложь, в PHP объекты передаются только по ссылке. Objects and references (%username% нужно ли разложить по полочкам почему это так — нужен ли отдельный топик посвященный способу передачи объектов. Я не хочу делать дурацкий топик-вопрос, по этому первый комментарий к этому посту будет вопросом «нужен ли отдельный топик посвященный способу передачи объектов» если да то плюсуем, если нет ставим минус)
    дальше пример автора
    PHP:
    <?php
    $arr = array(
    'key1' => 'value1',
    'key2' => 'value2',
    );
    
    function doSmthWithArray($arr) {
    $arr['key3'] = 'value3';
    }
    
    doSmthWithArray($arr);
    print_r($arr); // выведет "key1 => value1, key2 => value2" — исходный массив не изменился
    


    Javascript:
    var arr = {
    key1: 'value1',
    key2: 'value2'
    };
    
    function doSmthWithArray(arr) {
    arr['key3'] = 'value3';
    }
    
    doSmthWithArray(arr);
    console.log(arr); // выведет "key1 => value1, key2 => value2, key3 => value3" — т.к. в JS, по сути, нет встроенного типа «хеш», то это объект, и он передался по ссылке (впрочем, семантика передачи объектов — это отдельная тема. Конечно, просто сама по себе переменная представляет из себя ссылку на инстанс объекта, а не передача идет по ссылке, но это уже детали) 
    

    Итак пример более чем некорректен. Почему? Ну во первых в JavaScript почти всё является object -ми

    «JavaScript is almost entirely object-based. JavaScript objects are associative arrays, augmented with prototypes (see below). Object property names are string keys: obj.x = 10 and obj['x'] = 10 are equivalent, the dot notation being syntactic sugar. Properties and their values can be added, changed, or deleted at run-time. Most properties of an object (and those on its prototype inheritance chain) can be enumerated using a for...in loop. JavaScript has a small number of built-in objects such as Function and Date.» говорит нам Википедия
    Значит var arr полноценный объект передающийся по ссылке.

    В нашем любимом PHP тип array не является объектом. (Сколько всего типов в PHP? Ответ тут) а как мы с вами знаем только object передаётся по ссылке, всё остальное по значению. Вот почему в примере автора исходный массив остаётся неизменным. Можно ли привести массив к объекту? Да
    <?php
    $arr = array(
    'key1' => 'value1',
    'key2' => 'value2',
    );
    $ArrayObject = (object) $arr;
    var_dump($ArrayObject);
    $anotherArrayObject = new ArrayObject($arr);
    var_dump($anotherArrayObject);
    


    Либо явно преобразовываем к типу object либо используем встроенный класс ArrayObject в первом случае $ArrayObject становится объектом свойства которого это ключи исходного массива, а значения этих свойств — значения массива. Во втором случае наш массив стал объектом типа ArrayObject ознакомиться с которым вы можете по приведенной выше ссылке. А теперь когда наш массив стал объектом давайте-ка запустим пример автора оригинальной статьи с модификациями
    $arr = array(
    'key1' => 'value1',
    'key2' => 'value2',
    );
    $arr = new ArrayObject($arr);
    
    function doSmthWithArray($arr) {
    $arr['key3'] = 'value3';
    }
    
    doSmthWithArray($arr);
    print_r($arr);
    
    echo $arr['key3'];
    

    А теперь запустите этот код и посмотрите на результат! Ну что передаются объекты в PHP по ссылке?
    ArrayObject Object
    (
        [storage:ArrayObject:private] => Array
            (
                [key1] => value1
                [key2] => value2
                [key3] => value3
            )
    
    )
    value3
    

    Дальше у автора оригинальной статьи идет вот это:
    «Copy-on-write

    Вот об этом точно далеко не все знают. Если вкратце: хоть в PHP и всё передается по значению, но, на самом деле, копирование происходит далеко не всегда. Оно происходит, когда значение изменяется внутри конструкции, как, например, было в первом примере. Но это не единственный случай, когда создается копия. Подробнее об этом по ссылке.» Я не очень понял о чем это. Мы с вами уже выяснили, что простые типы передаются по значению объекты по ссылке.

    Всем дочитавшим до этого места огромное спасибо. Надеюсь я немного разъяснил путаницу с передачей объектов по ссылкам. Да не забываем про мини голосование. За любые неточности, ошибки, неприятное оформление прощу прощение заранее да и за то если этот топик нафиг никому не нужен :)

    UPD1: Господа это топик ответ на Отличие Javascript от PHP ;)
    UPD2: Минусующие с чем именно вы не согласны? В том что в PHP объект таки передаётся по ссылке?
    UPD3: Может я не правильно выразился но
    Передача параметра по значению

    Передача параметра по значению означает что вызывающая функция копирует в память, доступную вызываемой, (обычно стек) непосредственное значение. Изменение копии переменной, соответственно, оригинал не затрагивает.

    Передача параметра по ссылке
    Передача параметра по ссылке означает что копируется не само значение, а адрес исходной переменной.
    Передача по ссылке позволяет избежать копирования всей информации, описывающей состояние объекта. Изменение состояния параметра переданного по ссылке влечёт за собой изменения оригинального объекта.

    Таким образом, всё что я хотел сказать, что объекты и так передаются по ссылке, ( да на самом деле получается передача по значению адрес в памяти, по которому можно найти оригинальный объект ) Но давайте всё сведём к следующему простой тип передаётся по значению (Изменение копии переменной, соответственно, оригинал не затрагивает.)
    , объект по ссылке (Изменение состояния параметра переданного по ссылке влечёт за собой изменения оригинального объекта.)
    $test = 'LOREM IPSUM';
    function byValue($param) {
    	$param = strtolower($param);
    }
    byValue($test);
    echo $test.PHP_EOL;
    
    $object = new stdClass();
    function byReference($param){
    	$param->foo = 'bar';
    }
    byReference($object);
    var_dump($object);
    


    Мне в личку сыпятся вопросы, я на всё отвечу, просто сейчас не могу так как работаю. Отвечу как освобожусь спасибо.
    Поделиться публикацией

    Комментарии 75

      +24
      нужен ли отдельный топик посвященный способу передачи объектов
        +8
        не помешает так точно
          +7
          Глядя на современные продукты написанные на РНР мне иногда кажется что нужны даже тупые копипасты из мануала, ибо народ пошёл такой что даже основы знают не всегда…
            +3
            Именно. У PHP низкий уровень вхождения, но это не самое страшное. Самое страшное — некоторый народ учится не по мануалу PHP, а по каким-то левым пошаговым инструкциям типа «Как сделать движок блога за 5 шагов», в которых количество говнокода зашкаливает.
              0
              А ведь и мануал небезгрешен. Например, в нём сказано: «mysql_affected_rows() не работает с SELECT — только с запросами, модифицирующими таблицу». И я верил, потому как это логично. Но потом обнаружил, что на практике это не так. Как я понял, mysql_affected_rows() вызывает собственную функцию MySQL, а та, как сказано в мануале MySQL, «For SELECT statements, mysql_affected_rows() works like mysql_num_rows()».
                +2
                Во-первых, русский мануал уже много лет как официально не поддерживается, пользуйтесь английским.

                А во-вторых, если по-вашему, это действительно ошибка, воспользуйтесь ссылкой Report a bug, имеющейся прямо в тексте мануала, в правом верхнем углу.
                  0
                  Не могу. То есть читать по-английски могу, писать — не хочу, но тоже, в принципе, могу. Не могу зарепортить баг: bugs.php.net is down. Предлагают «remember your desired bug query and perform it later», но это не настолько ценно для меня.
                    0
                    если по-вашему, это действительно ошибка


                    А по-Вашему — нет? Я ожидаю, что функция mysql_affected_rows() вернёт после SELECT, как написано в английском мануале, «the number of affected rows by the last INSERT, UPDATE, REPLACE or DELETE query», а она возвращает число строк в выборке SELECT. Выходит, что говнокод, который мне приходится модифицировать,— прав, а мы с мануалом — нет.
                      0
                      По-моему — нет. affected rows — это затронутые ряды, но никак не возвращаемые ряды. Например, если в запросе используется некая группировка, то затронутых (прочитанных) рядов куда больше, чем реально возвращаемых. Так понятнее?

                      Но, так уж сложилось, что эта функция работает так, как работает. Я не знаю, как на протяжении времени менялось её поведение в MySQL, возможно раньше оно и не работало с select.

                      То есть, такое поведение — не задуманное, а «так получилось». Пользоваться им можно, но только на свой страх и риск, т.к. никто не гарантирует, что в будущем это поведение не поменяется (это поведение именно в php).

                      Хотя если быть уж совсем честным, то оно вряд ли поменяется.
                        +1
                        Во-первых, про то, что прочитанные ряды можно считать затронутыми, в мануале нет ни слова, зато есть перечень запросов, среди которых SELECT отсутствует. Во-вторых: а это вообще так? По-моему, нет. Вон, про UPDATE сказано: «When using UPDATE, MySQL will not update columns where the new value is the same as the old value. This creates the possibility that mysql_affected_rows() may not actually equal the number of rows matched, only the number of rows that were literally affected by the query».
                          0
                          Ещё раз, если вы считаете это багом, отпишите о нём, как поднимется bugs.php.net (это уже будет скоро). Там люди, которые лучше смогут рассудить нас.
                          This creates the possibility that mysql_affected_rows() may not actually equal the number of rows matched, only the number of rows that were literally affected by the query
                          В таком контексте для SELECT почти всегда должен возвращаться 0.
                            0
                            Вот и я говорю — должен. Но не возвращается.
                              +1
                              Вы правы, но не совсем. Если в мануале написано что mysql_affected_rows возвращает количество измененных строк для всего кроме селекта, значит они этот функционал не изменял, а вот за то что будет возвращаться для селекта они не дают гарантии, и не стоит на это надеяться. Как-то так.
                                +2
                                Не должен!

                                mysql_affected_rows() не рассчитан на работу с SELECT, по этому и в мане на эту тему ничего нет. А стало быть и использовать его таким образом нельзя. А если уж используете то на свой страх и риск (т.е говнокодите)
                                  0
                                  Никаких ограничений на использование mysql_affected_rows() в мануале нет. Да, в нём не описано, что она должна возвращать, если до неё не было ни одной из указанных SQL-операций; это недоработка.

                                  Но вполне возможна ситуация, которая подпадает под описание в мануале: когда сначала выполняется, скажем, UPDATE, потом SELECT, а потом вызывается функция mysql_affected_rows(). Согласно мануалу, функция в таком случае обязана вернуть число строк, модифицированных запросом UPDATE. А она возвращает число строк в выборке SELECT!
                                0
                                Ещё раз, если вы считаете это багом, отпишите о нём, как поднимется bugs.php.net (это уже будет скоро).


                                Бесполезно. Там уже был подобный багрипорт ещё пять лет назад. Они ответили, что это не баг PHP.

                                Конечно, это не баг PHP, это баг документации!
                                  0
                                  Тот баг закрыт правильно. Нужно сообщать именно об ошибке в документации (воспользовавшись ссылкой в доках), а не об ошибке «в модуле MySQL». Просто это разные команды, и реакция будет другой.
                                    –1
                                    Безответственные формалисты они. Ну да я уже направил им багрипорт именно с рубрикой документации, посмотрим, что будет.
                    +3
                    Вы знаете, иногда приходится Г-кодить. Я, вообще, дотнетчик. Довольно неплохой. Но приходится поддерживать часть проекта, писанную на PHP. Сегодня потребовалось сравнить значение двух строковых переменных на равенство. Вспомнил, что в PHP есть не только == и ===, но и strcmp() (и другие), решил поискать в интернетах, как же правильно… В конце концов, обратился к более опытному коллеге, который реализовывает ряд проектов на PHP с этим вопросом. Ответ был: «я всегда использую == и не парюсь, там какие-то различия есть, но я не сталкивался.»

                    Так это я к чему. К тому что порой бывает, что нет времени разобраться «как правильно», а надо сделать, «чтобы работало». И нет эксперта «под рукой», чтобы дал ответ и объяснил «почему так». В случае с PHP (в отличие от Java, например) мне часто не удаётся сходу найти решение и я делаю в стиле C#… Г-код? Наверняка, а что делать? Сам я предпочитаю изучать языки по книгам, но пока для PHP нет места в ближайшей очереди. К сожалению.

                    Прошу ни в коем случае не считать моё мнение призывом к холивару. Есть вещи, связанные с PHP, которые мне нравятся. Например, Drupal :)
                      +30
                      == сравнение данных.
                      === сравнение данных и типов
                      Жаль что ваш коллега не знает даже основ…
                        +7
                        >>К тому что порой бывает, что нет времени разобраться «как правильно», а надо сделать, «чтобы работало».

                        Если бывает что нет времени разобраться «как правильно» а изначально и незнали, то лучше отложить на потом а не сделать «абы как чтобы работало».
                        Особенно отложить и разобраться помогает мысль о том что кому то ваш код потом поддерживать

                        К томуже у PHP к его чести отличнейший мануал
                          +1
                          Я с Вами полностью согласен, это было не профессионально. Действительно стыдно за Г-код. Видимо, я не умею искать информацию…

                          Например, гугл-запрос «strings equality php» первыми двумя ссылками даёт отличнейший PHP мануал. И вот на какую из двух страниц ориентироваться?

                          php.net/manual/en/language.operators.comparison.php
                          php.net/manual/en/function.strcmp.php
                            0
                            Ориентироватся на обе.

                            Если нужно просто проверить на equality то '==='
                            Если нужно знать какая строка меньше или больше то 'strcmp'
                            И при использовании strcmp важно не забывать что она приводит типа при сравнеении так же как и оператор '=='

                            Вот простой код для того чтобы понять о типах
                            var_dump(strcmp(1, '1'));
                            var_dump(1 === '1');
                            var_dump('1' === '1');
                              0
                              Я бы добавил:
                              var_dump('0' == false); // true
                              var_dump('0' === false); // false
                              0
                              Что же тут неясного? strcmp возвращает -1, 0, 1, думаю понятно в каких случаях, а ==/=== просто true или false. Вам надо сравнить строки на равенство? Ну и используйте равенство.
                                0
                                Неясно было назначение. Теперь понял, что strcmp() предназначен для скорее сортировки, чем для сравнения.
                            +4
                            Это очень хорошо, когда есть эксперт «под рукой», причем, адекватный эксперт, у которого спросишь, и он ответит, а не начнет выебываться, мол, RTFM, lame!

                            RTFM — это, конечно, хорошо, но иногда на это, действительно, нет времени.

                            ps:// извините, сужу по сообществам различных ЯП в IRC сетях.
                              +1
                              Есть такое дело. В небольших веб студиях стоимость одного заказа невелика, и что бы оставаться в плюсе, приходится делать очень много маленьких проектов. Разработчикам в таких студиях некогда головы поднять, некогда разбираться в тонкостях и в том как на самом деле правильно.
                                +4
                                Вы бы уж лучше не позорили своего товарища, сначала называя его «опытным», а потом цитируя такие его слова.
                                  0
                                  Да, может не очень красиво. Но, а) товарищу может быть стимулом к изучению, как было сказано «основ»; б) товарища я совсем не спалил.
                                    0
                                    Да как раз наоборот. Именно с опытом приходит понимание, что зачастую проще и лучше сделать тяп-ляп, но быстро. И, если действительно понадобиться, потом уже дорабатывать/переделывать.
                                    0
                                    Г-код Г-коду рознь, одно дело когда есть рабочий сайт и что-то упало (и нужно срочно на г-кодить например форму для заказа пицы) другое дело когда идёт разработка серьезного продукта. Во втором случае если нет под рукой специалиста, то хочешь или нет, а его надо найти!!!
                                +2
                                Хабру нужны технические топики, и чем больше, тем лучше.
                                +8
                                > Я не очень понял о чем это. Мы с вами уже выяснили, что простые типы передаются по значению объекты по ссылке.

                                Он о том, что если передать в функцию массив, который внутри будет только читаться, но не изменяться, то этот массив не будет скопирован. Это легко заметить, если создать массив из сотни тысяч элементов и передать его в функцию, делая это в цикле. Если внутри функции изменить какой-нибудь элемент, то время выполнения скрипта заметно вырастет.
                                  0
                                  это всего лишь ленивые вычисления, которые не имеют никакого отношения к теме топика. создается копия или нет — не имеет значения, так как любые изменения переменной внутри функции никак не влияют на ее начальное состояние.
                                  0
                                  простые типы передаются по значению объекты по ссылке

                                  По идее, этого было бы достаточно — sapienti sat.

                                  В конце концов, есть ведь такой зонтичный термин — «ссылочные типы». В JS это все, кроме чисел и булевых значений (за исключением случаев, когда был сделан boxing, полагаю. Поправьте меня, если я ошибаюсь). В PHP, видимо, то же самое.
                                    +2
                                    Боюсь, что автор обрёк себя на эпичный провал с этой статьёй. И, видимо, с той, которую он планирует написать.

                                    Вот небольшой код, который показывает особенность указателей и ссылок:
                                    <?php
                                    function tonull1($variable)
                                        {
                                        $variable = null;
                                        }
                                    
                                    function tonull2(&$variable)
                                        {
                                        $variable = null;
                                        }
                                        
                                    $a = new stdClass(); //$a - содержит указатель на объект
                                    var_dump($a); //object(stdClass)[1]
                                    tonull1($a); //передали копию на указатель на объект, с указателем ничего не случилось
                                    var_dump($a); //object(stdClass)[1]
                                    tonull1(&$a); //передали ссылку на указатель на объект, указатель обнулился.
                                    var_dump($a); //null
                                    
                                    $a = new stdClass(); //$a - содержит указатель на объект
                                    var_dump($a); //object(stdClass)[1]
                                    tonull2($a); //функция примет ссылку на указатель на объект, указатель обнулился.
                                    var_dump($a); //null
                                    


                                    P.S. "… Я не очень понял о чем это. ..." — так настоящий оппонент не будет говорить.
                                      0
                                      А теперь замените в вашем коде функцию tonull1 на
                                      function tonull1($variable)
                                      {
                                          $variable->q=1;
                                      }
                                      

                                        0
                                        Впрочем, ваш пример показывает эту особенность www.php.net/manual/en/language.references.unset.php. В чем провал этой части статьи? По поводу Copy-on-write нижу напишу
                                          +1
                                          Пример с unset тут не подходит.
                                            0
                                            Я не сразу понял, к чему ваш комментарий, поэтому сначала написал про tonull1. По поводу unset — разве unset и присвоение null это не одно и то же?

                                            в примере
                                            $b =& $a;
                                            unset($a);

                                            у вас — есть указатель на объект, в функции другой указатель (копия) на этот объект (т.к. передано по нзначению). Вы присваете Null другому указателю на объект, сам объект и первый указатель на него при это остаются не тронуты. Разве не одно и то же с примером из мануала?

                                            В любом случае спасибо за комментарий, благодаря ему узнал про эти тонкости — раньше думал что объекты передаются по ссылке и все тут.
                                              0
                                              По поводу unset — разве unset и присвоение null это не одно и то же?

                                              Нет. Unset удаляет ссылку, а null присваивает значение.
                                              <?php
                                              $a = 1;
                                              $b = &$a;
                                              $c = &$a;
                                              unset($b);
                                              var_dump($a);
                                              $c = null;
                                              var_dump($a);
                                              ?>

                                              Результат: int(1) NULL
                                                0
                                                $a = new stdClass();
                                                $b =& $a;
                                                unset($a); //убирается ссылка
                                                var_dump($b); //object(stdClass)[1]
                                                
                                                $c = new stdClass();
                                                $d =& $c;
                                                $c = null; //изменилось значение 
                                                var_dump($d); //null
                                                
                                            +7
                                            Сейчас мне тоже наставят, но я не пойму почему вас минусуют, все правильно написали, а в статье ошибка.
                                            Выдежка из мануала www.php.net/manual/en/language.oop5.references.php

                                            One of the key-points of PHP5 OOP that is often mentioned is that «objects are passed by references by
                                            default». This is not completely true. This section rectifies that general thought using some examples.

                                            A PHP reference is an alias, which allows two different variables to write to the same value. As of PHP5, an object variable doesn't contain the object itself as value anymore. It only contains an object identifier which allows object accessors to find the actual object. When an object is sent by argument, returned or assigned to another variable, the different variables are not aliases: they hold a copy of the identifier, which points to the same object.

                                            Перевожу последнюю часть. Когда объект передается по значению, возвращается или присваивается другой переменной, переменные не становятся двумя названиями для одного объекта. Они содержат копию идентификатор (указателя), который указывает на один и тот же объект.

                                            Так что передача идет действительно по значению, просто по значению указателя, все как в Си. Просто вы передали не object, а object*.
                                              –2
                                              >One of the key-points of PHP5 OOP that is often mentioned is that «objects are passed by references by
                                              default». This is not completely true
                                              >а в статье ошибка.

                                              Это не совсем так:) А первоначальной статье все-таки ошибка — на основе неверного примера делались неверные выводы
                                                0
                                                Пример там был про то что все передается по значению, а случай с объектами не рассмотрели подробнее.
                                                Но фактически все работает также как если бы вы писали на Си и передавали указатель (потому что на самом деле $a = new stdClass(); и содержит указатель, а не сам объект). Т.е. вы передаете по значению, но указатель. Там снизу sectus, попытался еще объяснить, но по-моему только всех непонимающих запутает.
                                                  +1
                                                  по значению передавать указатель == передавать ссылку )

                                                  конечно, в C++ есть разница между указателями и ссылками, но в нашем случае это несущественно.
                                                    –1
                                                    Разница есть и здесь, вы можете изменить указатель, исходный объект при этом не изменится, что и пытался продемонстрировать sectus в посте выше.
                                                    Часто она не существенная, но хорошо бы понимать чтобы не удивляться, а что у меня фигня такая.
                                                    Тупейший пример:
                                                    $a = new stdClass();
                                                    $b = $a; // На самом деле тоже самое что передача в функцию
                                                    $b = null; // Испортили указатель, тут могло бы быть $b = new stdClass(); и что угодно еще
                                                    var_dump($a); //ничего не изменилось
                                                      +1
                                                      ну так чтобы поменять исходное, нужно передавать указатель на указатель на ))).
                                                0
                                                Бывает, ничего страшного: )
                                                +6
                                                Блин. Сложно опровергнуть опровержение, но попробую погнуть свою линию.

                                                Я пытаюсь опровергнуть вот это:
                                                ««… объекты по-прежнему являются значениями, но это значение представляет из себя ссылку на инстанс класса.» — ложь, в PHP объекты передаются только по ссылке.»

                                                И тем не менее это правда. Переменные не содержат объектов, они содержат указатели на объекты. Когда мы производим присваивание, то происходит копирование указателя на объект. Когда передаём по ссылке (используя &), то получаем ссылку на указатель на объект.

                                                Ну и, конечно, код, который это подтверждает (xdebug надо только поставить):
                                                $a = new stdClass();
                                                xdebug_debug_zval('a'); //(refcount=1, is_ref=0), object(stdClass)[1]  
                                                //refcount - количество ссылок на контейнер со значением
                                                //is_ref - является ли данная переменная частью набора ссылок на контейнер со значением
                                                
                                                $b = &$a;
                                                $с = &$b;
                                                xdebug_debug_zval('a'); //(refcount=3, is_ref=1), object(stdClass)[1]
                                                xdebug_debug_zval('b'); //(refcount=3, is_ref=1), object(stdClass)[1]
                                                xdebug_debug_zval('с'); //(refcount=3, is_ref=1), object(stdClass)[1]
                                                // тут всё понятно, набор состоит из 3 ссылок. a, b, c - как раз и составляет набор этих ссылок
                                                
                                                $d = $a;
                                                xdebug_debug_zval('d'); //(refcount=1, is_ref=0), object(stdClass)[1]
                                                // всего одна ссылка на контейнер (хотя объект скопирован не был). d - не принадлежит набору ссылок. Т.е. d - не ссылка и в $d = $a происходит именно копирование. Но копируется указатель на объект, а не сам объект.
                                                
                                                  0
                                                  Таким образом переменная а — указатель на объект, хранит в себе адрес объекта в памяти.
                                                  После копирования $d = $a; переменная d тоже хранит в себе этот адрес. Физически адрес объекта хранится в двух разных местах.

                                                  При $b = &$a; $с = &$b; у нас адрес объекта хранится физически в одном месте, при обращении к a, b и с указатель на объект берется из одной и той же ячейки памяти.

                                                  Верно?
                                                  0
                                                  Я ступил! Поставил статье плюс, а этому комментарию минус, хотя хотел наоборот.
                                                  Люди, верните справедливость! А меня можете заминусовать.
                                                  +1
                                                  Объекты передаются по указателю. Их также можно передать и по ссылке при помощи оператора &. Тогда поведение несколько изменится. Например:

                                                  <?php
                                                  class ClassA {}
                                                  class ClassB {}
                                                  
                                                  $a = new ClassA;
                                                  $b = $a;
                                                  $c = &$a;
                                                  $a = new ClassB;
                                                  var_dump($a,$b,$c);
                                                  /*
                                                  object(ClassB)#2 (0) { // $a
                                                  }
                                                  object(ClassA)#1 (0) { // $b
                                                  }
                                                  object(ClassB)#2 (0) { // $c
                                                  }
                                                  */
                                                  
                                                  +4
                                                  >«Copy-on-write… Я не очень понял о чем это. Мы с вами уже выяснили, что простые типы передаются по значению объекты по ссылке»

                                                  А вот тут теперь вы ошибаетесь. При передаче простого типа по значению его копия не будет создана, пока с ним не будет произведена операция записи.

                                                  Часто (по аналогии с другими языками) большие массивы для экономии памяти передают по ссылке в функцию. В функциях, которые не изменяют аргумент в php так делать необязательно.
                                                    0
                                                    Плюсую за тег «скандалы-интриги-расследования»
                                                    По существу темы холиварные какие-то
                                                      +9
                                                      жду статью Отличие Brainfuck'a от C# и ассемблера от 1c.
                                                        +2
                                                        неделя php и js на хабре?
                                                          –1
                                                          Назревает новый холивар
                                                          +7
                                                          Извините, но что одна статья, что другая — ужас. Не путайте людей, пусть они купят нормальный учебник или хотя бы откроют manual. Не удивительно, что PHP приобрел в массах дурную славу, если такие статьи появляются на хабре и выходят на главную.

                                                          Дальше у автора оригинальной статьи идет вот это: copy-on-write

                                                          Я не очень понял о чем это.

                                                          Может быть сначала стоило ознакомиться с информацией по теме, а потом уже писать статью-опровержение?
                                                            0
                                                            OK больше не буду
                                                            0
                                                            У меня у одного складывается мнение, что сравниваем несравнимое? А потом опровергаем. Ждём статьи Релодид, Из Бэк итд.
                                                              +6
                                                              Жду следующую статью из цикла «прочитал мануал, не понял — написал статью на хабре». Можно, например, про приведение типов порассуждать…
                                                                0
                                                                Накаркаете :)
                                                                  0
                                                                  А про приоритеты?
                                                                  0
                                                                  И вот хоть бы в одной статье указали как именно скопировать объект :) То что по ссылке всегда передается это понятно, а скопировать можно так: $copyedObject = clone $neededObject; Угнетает то что такие топики появляются… Вот человек начал учить пхп по какой-либо книге, прочитал, все примеры попробовал, обрадовался, все хорошо, но вот ему кто-то рассказал про ООП, человек соблазнился и полез искать примеры в инете, ну не ужели не понятно что куда надежнее будет залезть на оф.сайт и почитать доки там, ведь там все предельно ясно и понятно написано, даже в английском варианте, а если еще и читать комменты к каждой доке то можно еще несколько новых фишек узнать и попробовать :(
                                                                    0
                                                                    А в JS то как это сделать? JQuery версия и чистый-JS версия
                                                                      0
                                                                      в чистом JS для получения копии объекта надо писать свою рекурсивную функцию.
                                                                      точно не помню как в jQuery, но в Mootools'е для этого есть Object.Clone()
                                                                        0
                                                                        Не знаю, не силен в JavaScript'e :)
                                                                        0
                                                                        еще стоило бы напомнить, что иногда дальнейшая работа с точной копией существующего объекта может привести к совершенно непредсказуемым последствиям и что для избежания таких конфузов есть магический метод __clone
                                                                        +1
                                                                        Можно много спорить о терминах, как лучше что назвать.
                                                                        Но называть передачу объекта и передачу переменной с "&" одним и тем же термином — «передача по ссылки» неверно. Так как это совершенно разные «по ссылки».
                                                                        Из-за подобных путаниц в терминах и возникают подобные бессмысленные многабукфы и новички усваивают неверные понятия.
                                                                          +1
                                                                          «по ссылке», позор на мою седую голову не знающую склонений.
                                                                          +1
                                                                          Если погуглить, то можно найти тысячи подобных тем Difference Between JavaScript And PHP в каждой переливают из пустого в порожний. На вопрос «Чем отличается JavaScript от PHP» можно дать короткий ответ — «Всем». Такой же ответ можно дать на любой вопрос формата: «Чем отличается %lang_1% от %lang_2%?». Если бы каждый новый язык был бы похож 1 в 1 на предыдущий, то смысла бы в создании нового языка не было.
                                                                            0
                                                                            С точки зрения программиста-прикладника по ссылке передаются объектные типы, по значению — все остальные (так, как это написано во всех мануалах).

                                                                            С системной точки зрения, так, как это технически происходит на самом деле — ВСЕ переменные передаются по ссылке. Чтобы обеспечить такое поведение, какое ожидает программист-прикладник, система (компилятор) выполняет некоторые неявные действия.

                                                                            Пример. Передаётся в функцию по значению переменная с типом строка. Следовательно, изменения переменной внутри функции должны остаться сугубо локальными. Но технически, как было ранее сказано, строка передаётся по ссылке. Внутри функции компилятор НЕЯВНО наращивает на единицу счётчик ссылок на объект-строку, а перед выходом из функции уменьшает счётчик на единицу. В случае изменения значения переменной внутри функции, выполняется НЕЯВНОЕ копирование переменной. В этом, собственно, заключается механизм Copy On Write.

                                                                            Другой пример. Передаётся в функцию по ссылке (используя &) переменная объектного типа. Компилятор проверит счётчик ссылок на этот объект. Если значение счётчика ссылок равно единице, то будет сразу передана эта ссылка. Но, если он больше единицы, компилятор НЕЯВНО создаст копию объекта и передаст ссылку на эту копию.

                                                                            Таким образом, споры происходят из-за того, что одно и то же явление рассматривается с разных точек зрения — точки зрения ПРИКЛАДНОЙ и точки зрения СИСТЕМНОЙ.
                                                                            Описанные мной выше системные механизмы иногда позволяют передаче по значению выглядеть как передача по ссылке (без РЕАЛЬНОГО копирования переменной) и наоборот, передаче по ссылке выглядеть как передаче по значению (с РЕАЛЬНЫМ копированием переменной).

                                                                            Кстати, из вышесказанного можно сделать один вывод — если вы не меняете значение переменной внутри функции, то нет никакого смысла передавать ее, используюя &. Это не даст никакого выигрыша в производительности, напротив, в некоторых случаях, может только её понизить.

                                                                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                                            Самое читаемое